How to define string arrays in Data Contract? - datacontractserializer

I have a string array in datacontract as below
[DataMember(Name = "photos", IsRequired = true, Order = 3)]
public string[] photos { get; set; }
In WCF REST Service call I am passing below xml input for this string array
<photos>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/1227132014-bmw-x1_100426158_m.jpg</string>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/122713bmw2.jpg</string>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/122713bmw3.jpg</string>
<string>http://localhost:13169/MainPortal/ContentLibrary/21/58/122713BMW_Hamann_Laguna_Seca.jpg</string><string>http://localhost:13169/MainPortal/ContentLibrary/21/58/1227132014-BMW-X1-SUV-sDrive-28i-4dr-4x2-Sports-Activity-Vehicle-Exterior-2.png</string>
</photos>
My client code able to make WebService call with passing xml in HttpWebRequest without any issues, from the service I could see all other data coming in except this string array. Am I missing something in DataContract to serialize arrays. Please help
Tried with CollectionDataContract as below still no luck
[CollectionDataContract(Name = "photos")]
public class Photos : Collection<string>
Also added KnownTypes which is however not required for ordinal types
[KnownType(typeof(string[]))]
public class PublishPhotos
{
Here is complete data contract class
[DataContract(Namespace = "http://myurl.com/Publisher")]
[KnownType(typeof(string[]))]
public class PublishPhotos
{
[DataMember(Name = "publicationId", IsRequired = true, Order = 0)]
public int publicationId { get; set; }
[DataMember(Name = "issueId", IsRequired = true, Order = 1)]
public string issueId { get; set; }
[DataMember(Name = "contentId", IsRequired = true, Order = 2)]
public string contentId { get; set; }
[DataMember(Name = "photos", IsRequired = true, Order = 3)]
public Photos photos { get; set; }
}

Finally I figured out what went wrong with XML in HttpWebRequest, the issue is with serializing string array. The easiest way I could have figured out through visiting /PublisherSvc.svc/help for string it requires namespace http://schemas.microsoft.com/2003/10/Serialization/Arrays as below
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">http://localhost:8081/photos/1/1.jpg</string>
Hope this helps someone facing similar issue

I have figured out the answer to this problem. Thanks to #HarlanB
I have changed data contract from DataContract Serialization to XmlSerialization
[SerializableAttribute()]
[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "http://myUrl.com/Publisher", IsNullable = false)]
public class PublishPhotos
{
//[DataMember(Name = "publicationId", IsRequired = true, Order = 0)]
[XmlElementAttribute(ElementName="publicationId", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
public int publicationId { get; set; }
//[DataMember(Name = "issueId", IsRequired = true, Order = 1)]
[XmlElementAttribute(ElementName = "issueId", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 1)]
public string issueId { get; set; }
//[DataMember(Name = "contentId", IsRequired = true, Order = 2)]
[XmlElementAttribute(ElementName = "contentId", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 2)]
public string contentId { get; set; }
//[DataMember(Name = "photos", IsRequired = true, Order = 3)]
[XmlElementAttribute(ElementName = "photos", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 3)]
public string[] photos { get; set; }
}
In client code I am using XmlSerializer to write to HttpWebRequest as below
pubPhotos.publicationId = Convert.ToInt32(publication.Value);
pubPhotos.issueId = secName;
pubPhotos.contentId = selectedMediaItem;
HtmlDocument divDoc = new HtmlDocument();
divDoc.LoadHtml(widgetScript);
HtmlNode divNode = divDoc.DocumentNode.FirstChild;
HtmlNodeCollection imgs = divNode.SelectNodes("//img");
Collection<string> photos = new Collection<string>();
foreach (HtmlNode img in imgs)
{
photos.Add(img.Attributes["src"].Value);
}
pubPhotos.photos = photos.ToArray();
HttpWebRequest req = null;
const string url = "http://localhost:40009/PublisherSvc.svc/PublishPhotos";
req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/xml; charset=utf-8";
req.KeepAlive = false;
req.Timeout = 30000;
req.Headers.Add("SOAPAction", url);
XmlSerializer serilizer = new XmlSerializer(typeof(PublishPhotos));
var sw = new StreamWriter(req.GetRequestStream());
serilizer.Serialize(sw, pubPhotos);
sw.Close();
I hope this helps some other people out there that are having similar problems.

Related

Keycloack does not detect #SqlResultSetMapping in custom provider jar

I am trying to create a custom query in Keycloak in my custom provider Jar. The annotation below is not detected. I had to resort to use the call that returns a list of objects from which I can extract the columns from the result set. However I would like to use the SqlResultSetMapping interface. Here is the code that I am using.
#MappedSuperclass
#SqlResultSetMapping( name = "GroupTabularDataMapping",
classes = {
#ConstructorResult(
targetClass = GroupTabularData.class,
columns = {
#ColumnResult(name = "id"),
#ColumnResult(name = "name"),
#ColumnResult(name = "updated_by"),
#ColumnResult(name = "updated_by_email"),
#ColumnResult(name = "last_updated"),
#ColumnResult(name = "count",type = Long.class)
})
})
public class GroupTabularData {
private String id;
private String name;
private String updatedBy;
private String updatedByEmail;
private String lastUpdated;
private BigInteger count;
public GroupTabularData(String id, String name, String updatedBy, String updatedByEmail,
String lastUpdated, BigInteger count) {
this.id = id;
this.name = name;
this.updatedBy = updatedBy;
this.updatedByEmail = updatedByEmail;
this.lastUpdated = lastUpdated;
this.count = count;
}
public GroupTabularData(Object objArr) {
Object[] arr = (Object[]) objArr;
this.id = arr[0].toString();
this.name = arr[1].toString();
this.updatedBy = arr[2].toString();
this.updatedByEmail = arr[3].toString();
this.lastUpdated = arr[4].toString();
this.count = (BigInteger)arr[5];
}
}
This call works:
Object resultData = q.getResultList().stream().map(
objArr -> new GroupTabularData(objArr)).collect(Collectors.toList());
But this one does not:
Query q = em.createNativeQuery(GROUP_TABULAR_QUERY, "GroupTabularDataMapping");
List<GroupTabularData> resultData = q.getResultList();
I imagine that the reason is because I need to add my class to the scanning list of JPA but I don't know which file I need to update or if it is some other configuration. I appreciate any leads.

LiteDb class deserialization is not working

I have B class that has a class A as member. The LiteDb store it correctly as I see in LiteDB Studio. "As" collection is also OK. Why is it not right in the deserialization? Class A has a BsonCtor. B also
namespace ConsoleAppTestDeserializatioBug {
class Program {
public class A {
public A() { A_ID = ObjectId.NewObjectId(); }
[BsonCtor]
public A(ObjectId id, string name) { A_ID = id; Name = name; }
[BsonId]
public ObjectId A_ID { get; set; }
public string Name { get; set; }
public const string CollectionName = "As";
}
public class B {
public const string CollectionName = "Bs";
public B() { B_ID = ObjectId.NewObjectId(); }
[BsonCtor]
public B(ObjectId id, int dummy, A a) { B_ID = id; Dummy = dummy; aObj = a;}
[BsonId]
public ObjectId B_ID { get; set; }
public int Dummy { get; set; }
[BsonRef(A.CollectionName)]
public A aObj { get; set; }
}
private LiteDatabase _LiteDatabase;
static void Main(string[] args) {
var p = new Program();
p.Test();
}
private void Test() {
A a = new A(); // Create my Object
a.Name = "Name123";
var initialId = a.A_ID;
B b = new B();
b.Dummy = 123;
b.aObj = a;
_LiteDatabase = new LiteDatabase(new ConnectionString(#"C:\Temp\tst1.db") { Connection = ConnectionType.Shared });
ILiteCollection<A> aas = _LiteDatabase.GetCollection<A>(A.CollectionName);
aas.Insert(a);
ILiteCollection<B> bs = _LiteDatabase.GetCollection<B>(B.CollectionName);
bs.Insert(b);
// Get in the DB
var bb = bs.FindAll().ToArray()[0];
var aa = bb.aObj;
var aaid = aa.A_ID;
if (aaid == initialId) { Console.WriteLine("Id is correct");}
var aname = aa.Name; // aname i s null!!!!! and why
}
}
}
I found an answer in LiteSB DbRef
I must just add an "include" in my query:
var bb = bs.Include(x => x.aObj).FindAll().ToArray()[0];

required for input parameters on swagger

when I use #RequestParam with required = true on rest and while testing this on swagger, it will be shown along with *required mark next to it.
#GetMapping(path = "/getinfo")
public ResponseEntity<?> getMyInfo(#RequestParam(value = "input", required = true) int input, other request parameters)
But now how can I achieve same on swagger if i have mapped url with object using #ModelAttribute .
#GetMapping(path = "/getinfo")
public ResponseEntity<?> getMyInfo(#ModelAttribute MyObject myObject)
You can try using the annotation #ApiParam
#GetMapping(path = "/getinfo")
public ResponseEntity<?> getMyInfo(#ModelAttribute("myObject") MyObject myObject)
Inside your MyObject class
public class MyObject {
private long id;
#ApiParam(name = "name", value = "Name is Mandatory", required = true)
private String name;
}
Now, name will be a *required field.

ASP.NET MVC class inheritence and LINQ

I'm having a problem with LINQ to entities which I've resolved, but want to make sure I've resolved in the right way.
I have 2 classes:
namespace ShopTest.Models
{
public class Shop
{
public int ShopID { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postcode { get; set; }
public string Country { get; set; }
public decimal Latitude { get; set; }
public decimal Longitude{ get; set; }
}
[NotMapped]
public class ShopLocation : Shop
{
public decimal AddressLatitude { get; set; }
public decimal AddressLongitude { get; set; }
public decimal DistanceFromAddress
{
get
{
return Convert.ToDecimal(
Math.Sqrt(
Math.Pow(Convert.ToDouble(this.Latitude - this.AddressLatitude), 2.0)
+
Math.Pow(Convert.ToDouble(this.Longitude- this.AddressLongitude), 2.0)
)
* 62.1371192
);
}
}
}
}
When querying in LINQ, I originally tried:
decimal lat = Convert.ToDecimal(-33.8736510, NumberFormatInfo.InvariantInfo);
decimal lng = Convert.ToDecimal(151.2068896, NumberFormatInfo.InvariantInfo);
var nearbyShops = from c in db.Shops
where Math.Abs(c.lat - lat) < 0.25M &&
Math.Abs(c.lng - lng) < 0.25M
select new NearbyShopLocation()
{
StoreNumber = store.StoreNumber,
Address = store.Address,
City = store.City,
Region = store.Region,
CountryCode = store.CountryCode,
PostalCode = store.PostalCode,
Latitude = store.Latitude,
Longitude = store.Longitude,
AddressLatitude = lat,
AddressLongitude = lng
};
var nearbySortedShops = nearbyShops.ToList().OrderBy(s => s.DistanceFromAddress).ToList();
However I kept getting the error "The entity or complex type 'ShopTest.Controllers.Shops' cannot be constructed in a LINQ to Entities query"
I've fixed the issue with the below code, but it doesn't make sense why this would work - being new to MVC I'm hoping someone can explain it. :-)
var nearbyShops = (from c in db.Shops
where Math.Abs(c.lat - lat) < 0.25M &&
Math.Abs(c.lng - lng) < 0.25M
select new
{
StoreNumber = c.StoreNumber,
Address = c.Address,
City = c.City,
Country = c.Country,
PostalCode = c.PostalCode,
Latitude = c.Latitude,
Longitude = c.Longitude,
}).ToList().Select(l => new ShopLocation
{
Name = l.Name,
City = l.City,
State = l.State,
Country = l.Country,
Lat = l.Lat,
Lng = l.Lng,
AddressLatitude = lat,
AddressLongitude = lng
}).ToList().OrderBy(s => s.DistanceFromAddress).ToList();
Have I done this correctly? Is there a better way?
EF has limitation that you cannot build mapped entity manually in the query. That means you cannot do this:
var shops = from s in db.Shops where ... select new Shop { ... };
This also involves derived entities. Because of that you first have to call ToList to switch to Linq-to-Objects:
var shopse = db.Shops.Where(...).ToList().Select(s => new Shop { ... });
Generally you should be OK with:
var nearbyShops =
(from c in db.Shops
where Math.Abs(c.lat - lat) < 0.25M &&
Math.Abs(c.lng - lng) < 0.25M
select c).ToList()
.Select(l => new ShopLocation
{
Name = l.Name,
City = l.City,
State = l.State,
Country = l.Country,
Lat = l.Lat,
Lng = l.Lng,
AddressLatitude = lat,
AddressLongitude = lng
}).OrderBy(s => s.DistanceFromAddress).ToList();

EclipseLink GeneratedValue null on postgres only on one entity

I have a rather weird case. I have some entities generated with netbeans and i can persist all except one. I see no difference in the database nor in the entity class. Can someone help me, here is my entity class , database, and error that i am receiving
CREATE TABLE objekat
(
id_objekat bigserial NOT NULL,
id_opstina serial NOT NULL,
naziv character varying(50) NOT NULL,
kapacitet character varying(50),
adresa character varying(100),
lokacija_sirina double precision,
lokacija_duzina double precision,
opis character varying(500),
korisnicko_ime character varying(50),
sifra character varying(50),
maks_broj_slike integer,
absolute_path_logo character varying(255),
CONSTRAINT objekat_pkey PRIMARY KEY (id_objekat),
CONSTRAINT fkobjekat924176 FOREIGN KEY (id_opstina)
REFERENCES opstina (id_opstina) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
and this is my entity bean.
#Entity
#Table(name = "objekat")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Objekat.findAll", query = "SELECT o FROM Objekat o"),
#NamedQuery(name = "Objekat.findByIdObjekat", query = "SELECT o FROM Objekat o WHERE o.idObjekat = :idObjekat"),
#NamedQuery(name = "Objekat.findByNaziv", query = "SELECT o FROM Objekat o WHERE upper (o.naziv) like upper(:naziv)"),
#NamedQuery(name = "Objekat.findByNazivAndOpstina", query = "SELECT o FROM Objekat o inner join o.idOpstina op WHERE upper (o.naziv) like upper(:naziv) and op.idOpstina = :idOpstina"),
#NamedQuery(name = "Objekat.findByKapacitet", query = "SELECT o FROM Objekat o WHERE o.kapacitet = :kapacitet"),
#NamedQuery(name = "Objekat.findByAdresa", query = "SELECT o FROM Objekat o WHERE o.adresa = :adresa"),
#NamedQuery(name = "Objekat.findByLokacijaSirina", query = "SELECT o FROM Objekat o WHERE o.lokacijaSirina = :lokacijaSirina"),
#NamedQuery(name = "Objekat.findByLokacijaDuzina", query = "SELECT o FROM Objekat o WHERE o.lokacijaDuzina = :lokacijaDuzina")})
public class Objekat implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_objekat",columnDefinition = "BIGSERIAL")
private Long idObjekat;
#Size(max = 255)
#Column(name = "absolute_path_logo")
private String absolutePathLogo;
#OneToMany( mappedBy = "objekatidObjekat")
private List<DogadjajObjekat> dogadjajObjekatList;
#OneToMany( mappedBy = "objekatidObjekat")
private List<SlikeLokacijaObjekat> slikeLokacijaObjekatList;
#OneToMany( mappedBy = "idObjekat")
private List<RasporedObjekat> rasporedObjekatList;
#Column(name = "maks_broj_slike")
private Integer maksBrojSlike;
#Size(max = 50)
#Column(name = "korisnicko_ime")
private String korisnickoIme;
#Size(max = 50)
#Column(name = "sifra")
private String sifra;
#Size(max = 500)
#Column(name = "opis")
private String opis;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "lokacija_sirina")
private Double lokacijaSirina;
#Column(name = "lokacija_duzina")
private Double lokacijaDuzina;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 50)
#Column(name = "naziv")
private String naziv;
#Size(max = 50)
#Column(name = "kapacitet")
private String kapacitet;
#Size(max = 100)
#Column(name = "adresa")
private String adresa;
#JoinTable(name = "tip_objekta_objekat", joinColumns = {
#JoinColumn(name = "objekatid_objekat", referencedColumnName = "id_objekat")}, inverseJoinColumns = {
#JoinColumn(name = "tip_objektaid_tip_objekta", referencedColumnName = "id_tip_objekta")})
#ManyToMany
private List<TipObjekta> tipObjektaList;
#JoinColumn(name = "id_opstina", referencedColumnName = "id_opstina")
#ManyToOne(optional = false)
private Opstina idOpstina;
public Objekat() {
}
public Objekat(Long idObjekat) {
this.idObjekat = idObjekat;
}
public Objekat(Long idObjekat, String naziv) {
this.idObjekat = idObjekat;
this.naziv = naziv;
}
public Long getIdObjekat() {
return idObjekat;
}
public void setIdObjekat(Long idObjekat) {
this.idObjekat = idObjekat;
}
public String getNaziv() {
return naziv;
}
public void setNaziv(String naziv) {
this.naziv = naziv;
}
public String getKapacitet() {
return kapacitet;
}
public void setKapacitet(String kapacitet) {
this.kapacitet = kapacitet;
}
public String getAdresa() {
return adresa;
}
public void setAdresa(String adresa) {
this.adresa = adresa;
}
#XmlTransient
public List<TipObjekta> getTipObjektaList() {
return tipObjektaList;
}
public void setTipObjektaList(List<TipObjekta> tipObjektaList) {
this.tipObjektaList = tipObjektaList;
}
public Opstina getIdOpstina() {
return idOpstina;
}
public void setIdOpstina(Opstina idOpstina) {
this.idOpstina = idOpstina;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idObjekat != null ? idObjekat.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Objekat)) {
return false;
}
Objekat other = (Objekat) object;
if ((this.idObjekat == null && other.idObjekat != null) || (this.idObjekat != null && !this.idObjekat.equals(other.idObjekat))) {
return false;
}
return true;
}
#Override
public String toString() {
return "rs.dzetSet.entiteti.Objekat[ idObjekat=" + idObjekat + " ]";
}
public String getOpis() {
return opis;
}
public void setOpis(String opis) {
this.opis = opis;
}
public Double getLokacijaSirina() {
return lokacijaSirina;
}
public void setLokacijaSirina(Double lokacijaSirina) {
this.lokacijaSirina = lokacijaSirina;
}
public Double getLokacijaDuzina() {
return lokacijaDuzina;
}
public void setLokacijaDuzina(Double lokacijaDuzina) {
this.lokacijaDuzina = lokacijaDuzina;
}
public String getKorisnickoIme() {
return korisnickoIme;
}
public void setKorisnickoIme(String korisnickoIme) {
this.korisnickoIme = korisnickoIme;
}
public String getSifra() {
return sifra;
}
public void setSifra(String sifra) {
this.sifra = sifra;
}
public Integer getMaksBrojSlike() {
return maksBrojSlike;
}
public void setMaksBrojSlike(Integer maksBrojSlike) {
this.maksBrojSlike = maksBrojSlike;
}
public void pocevajMaksBrojSlike(){
this.maksBrojSlike++;
}
public String getAbsolutePathLogo() {
return absolutePathLogo;
}
public void setAbsolutePathLogo(String absolutePathLogo) {
this.absolutePathLogo = absolutePathLogo;
}
#XmlTransient
public List<RasporedObjekat> rasporedObjekatListPrePodne(){
List<RasporedObjekat> rez = new ArrayList<RasporedObjekat>();
if(rasporedObjekatList==null){
rasporedObjekatList = new ArrayList<RasporedObjekat>();
}
for(RasporedObjekat ro:rasporedObjekatList){
if(!ro.getVecernjiProgram()){
rez.add(ro);
}
}
return rez;
}
#XmlTransient
public List<RasporedObjekat> rasporedObjekatListPoslePodne(){
List<RasporedObjekat> rez = new ArrayList<RasporedObjekat>();
if(rasporedObjekatList==null){
rasporedObjekatList = new ArrayList<RasporedObjekat>();
}
for(RasporedObjekat ro:rasporedObjekatList){
if(ro.getVecernjiProgram()){
rez.add(ro);
}
}
return rez;
}
#XmlTransient
public List<DogadjajObjekat> getDogadjajObjekatList() {
return dogadjajObjekatList;
}
public void setDogadjajObjekatList(List<DogadjajObjekat> dogadjajObjekatList) {
this.dogadjajObjekatList = dogadjajObjekatList;
}
#XmlTransient
public List<SlikeLokacijaObjekat> getSlikeLokacijaObjekatList() {
return slikeLokacijaObjekatList;
}
public void setSlikeLokacijaObjekatList(List<SlikeLokacijaObjekat> slikeLokacijaObjekatList) {
this.slikeLokacijaObjekatList = slikeLokacijaObjekatList;
}
#XmlTransient
public List<RasporedObjekat> getRasporedObjekatList() {
return rasporedObjekatList;
}
public void setRasporedObjekatList(List<RasporedObjekat> rasporedObjekatList) {
this.rasporedObjekatList = rasporedObjekatList;
}
and i persist it in a rather normal way, or i just think so.
utx.begin();
if(noviObjekat.getIdObjekat() == null){
em.persist(noviObjekat);
}else{
em.merge(noviObjekat);
}
utx.commit();
and i get a pretty weird error
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: null value in column "id_opstina" violates not-null constraint
Error Code: 0
Call: INSERT INTO objekat (absolute_path_logo, adresa, kapacitet, korisnicko_ime, lokacija_duzina, lokacija_sirina, maks_broj_slike, naziv, opis, sifra, id_opstina) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [11 parameters bound]
Query: InsertObjectQuery(rs.dzetSet.entiteti.Objekat[ idObjekat=null ])
}
You set a generator on the field for "id_objekat" but the exception is for the not-null constraint on "id_opstina". You will need to set this field yourself or use a returning policy to get it instead:
http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_(ELUG)#Using_EclipseLink_JPA_Extensions_for_Returning_Policy