Convert Soap XML response to Object Java with JAXB - java

I have a response XML that I need to add in a Java object to use it, however this is null when I try to access something from it.
I tried to make an unmarshal of it but without success
The Body of XML received is this.
<ns1:buscaCadastroImobiliarioGeralResponse>
<return xsi:type="ns1:retornoBuscaCadbciGeral">
<cadastros SOAP-ENC:arrayType="ns1:cadastros[1]" xsi:type="ns1:listaCadastros">
<item xsi:type="ns1:cadastros">
<codigo_cadastro >xsi:type="xsd:string">461954</codigo_cadastro>
The code that is executed
BuscaCadastroImobiliarioGeral request = objectFactory.createBuscaCadastroImobiliarioGeral();
Entrada entrada = new Entrada();
entrada.setCodigoCadastro("461954");
request.setEntrada(entrada);
BuscaCadastroImobiliarioGeralResponse response = (BuscaCadastroImobiliarioGeralResponse) client.callWebService("url", request);
System.out.println(response.getReturnResponse());
public class SOAPConnector extends WebServiceGatewaySupport{
public Object callWebService(String url, Object request) {
return getWebServiceTemplate().marshalSendAndReceive(url, request);
}
}
The problem is that when I get getReturnResponse it always comes null. Above is the classes of model
CLASS BuscaCadastroImobiliarioGeralResponse
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"returnResponse"
})
#XmlRootElement(name = "buscaCadastroImobiliarioGeralResponse")
public class BuscaCadastroImobiliarioGeralResponse {
#XmlElement(name = "return", required = true)
private ReturnResponse returnResponse;
public ReturnResponse getReturnResponse() {
return returnResponse;
}
public void setReturnResponse(ReturnResponse returnResponse) {
this.returnResponse = returnResponse;
}
}
CLASS ReturnResponse
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "return", propOrder = {
"cadastros"
})
#XmlRootElement(name = "return")
#XmlSeeAlso(ReturnResponse.class)
public class ReturnResponse {
#XmlElement(required = true)
private List<Cadastros> cadastros;
public List<Cadastros> getCadastros() {
return cadastros;
}
public void setCadastros(List<Cadastros> cadastros) {
this.cadastros = cadastros;
}
}
CLASS Cadastros
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "cadastros", propOrder = {
"item"
})
#XmlRootElement(name = "cadastros")
#XmlSeeAlso(Cadastros.class)
public class Cadastros {
#XmlElement
private Item item;
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
Problema relacionado: Spring Web service unmarshalling not happening correctly

Related

Attribute to a JAXB Element

I'm using JAXB for creating xml. I want to set attribute 'lang' on elements PrimaryValue and AlternativeSpelling.
<AgencyOrUnit>
<PrimaryValue lang="el">ΓΑΔΑ</PrimaryValue>
<AlternativeSpelling lang="en">Athens General Police Directorate</AlternativeSpelling>
</AgencyOrUnit>
Here's my code:
#XmlRootElement(name = "OwnerReference")
#XmlType(propOrder = { "primaryValue", "alternativeSpelling"})
public class AgencyOrUnit {
private String PrimaryValue;
private String AlternativeSpelling;
public String getPrimaryValue() {
return PrimaryValue;
}
public void setPrimaryValue(String PrimaryValue){
this.PrimaryValue = PrimaryValue;
}
public String getAlternativeSpelling() {
return AlternativeSpelling;
}
public void setAlternativeSpelling(String AlternativeSpelling){
this.AlternativeSpelling = AlternativeSpelling;
}
}
Here's process of marshalling:
AgencyOrUnit agencyOrUnit = new AgencyOrUnit();
agencyOrUnit.setPrimaryValue("ΓΑΔΑ");
agencyOrUnit.setAlternativeSpelling("General Police");
The problem is that I don't know how to set property with value on elements primaryValue and alternativeSpelling?
You can use annotations #XmlValue & #XmlAttribute but you need to create a new class to hold both lang and the original value string. Something like this:
#Setter
#AllArgsConstructor
public class LocaleString {
private String lang;
private String value;
#XmlAttribute
public String getLang() {
return lang;
}
#XmlValue
public String getValue() {
return value;
}
}
Then modify your AgencyOrUnit accordingly:
#XmlRootElement(name = "OwnerReference")
#XmlType(propOrder = { "primaryValue", "alternativeSpelling"})
#Getter #Setter
public class AgencyOrUnit {
private LocaleString PrimaryValue;
private LocaleString AlternativeSpelling;
}
Test it:
#Test
void test() throws JAXBException {
AgencyOrUnit agencyOrUnit = new AgencyOrUnit();
agencyOrUnit.setPrimaryValue(new LocaleString("el", "ΓΑΔΑ"));
agencyOrUnit.setAlternativeSpelling(new LocaleString("en", "General Police"));
JAXBContext ctx = JAXBContext.newInstance(AgencyOrUnit.class);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(agencyOrUnit, System.out);
}
and you should see this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OwnerReference>
<primaryValue lang="el">ΓΑΔΑ</primaryValue>
<alternativeSpelling lang="en">General Police</alternativeSpelling>
</OwnerReference>

manually create annotate classes for nested namespace in jaxb

I want to have JAXB-annotated classes which would be marshalled/unmarshalled to different XML namespaces.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://test.com/">
<soapenv:Header/>
<soapenv:Body>
<v1:UpdateMemberRequest>
<v1:memberID>568</v1:memberID>
<v1:member>
<v1:Address>USA</v1:Address>
</v1:member>
</v1:UpdateMemberRequest>
</soapenv:Body>
</soapenv:Envelope>
how will the class look like?
Below the required Java classes. Add getters and setters according to standard practice. In package com.test;:
// MemberType.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "MemberType", propOrder = {
"address"
})
public class MemberType {
#XmlElement(name = "Address", required = true)
protected String address;
}
// UpdateMemberRequestType.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "UpdateMemberRequestType", propOrder = {
"memberID",
"member"
})
public class UpdateMemberRequestType {
#XmlElement(required = true)
protected String memberID;
#XmlElement(required = true)
protected MemberType member;
}
// ObjectFactory.java
#XmlRegistry
public class ObjectFactory {
private final static QName _UpdateMemberRequest_QNAME =
new QName("http://test.com/", "UpdateMemberRequest");
public ObjectFactory() {
}
public UpdateMemberRequestType createUpdateMemberRequestType() {
return new UpdateMemberRequestType();
}
public MemberType createMemberType() {
return new MemberType();
}
#XmlElementDecl(namespace = "http://test.com/",
name = "UpdateMemberRequest")
public JAXBElement
createUpdateMemberRequest(UpdateMemberRequestType value) {
return new JAXBElement(_UpdateMemberRequest_QNAME,
UpdateMemberRequestType.class, null, value);
}
}
Another package org.xmlsoap.schemas.soap.envelope;:
// BodyType.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "BodyType", propOrder = {
"updateMemberRequest"
})
public class BodyType {
#XmlElement(name = "UpdateMemberRequest", namespace = "http://test.com/", required = true)
protected UpdateMemberRequestType updateMemberRequest;
}
// EnvelopeType.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "EnvelopeType", propOrder = {
"header",
"body"
})
public class EnvelopeType {
#XmlElement(name = "Header", required = true)
protected String header;
#XmlElement(name = "Body", required = true)
protected BodyType body;
}
// ObjectFactory.jav
#XmlRegistry
public class ObjectFactory {
private final static QName _Envelope_QNAME =
new QName("http://schemas.xmlsoap.org/soap/envelope/", "Envelope");
public ObjectFactory() {
}
public EnvelopeType createEnvelopeType() {
return new EnvelopeType();
}
public BodyType createBodyType() {
return new BodyType();
}
#XmlElementDecl(namespace = "http://schemas.xmlsoap.org/soap/envelope/",
name = "Envelope")
public JAXBElement createEnvelope(EnvelopeType value) {
return new JAXBElement(_Envelope_QNAME,
EnvelopeType.class, null, value);
}
}

how can JAXB generate such an element <_ /> with my object?

Here is my object:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"profile", "request", "filter"})
#XmlRootElement(name = "SubmitXml")
public class SubmitXml {
#XmlElement(name = "Profile")
protected String profile;
#XmlElement(name = "Request")
protected SubmitXml.Request request;
#XmlElement(name = "Filter")
protected SubmitXml.Filter filter;
public String getProfile() {
return profile;
}
public void setProfile(String value) {
this.profile = value;
}
public SubmitXml.Request getRequest() {
return request;
}
public void setRequest(SubmitXml.Request value) {
this.request = value;
}
public SubmitXml.Filter getFilter() {
return filter;
}
public void setFilter(SubmitXml.Filter value) {
this.filter = value;
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"any"
})
public static class Filter {
#XmlAnyElement(lax = true)
protected Object any;
public Object getAny() {
return any;
}
public void setAny(Object value) {
this.any = value;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"any"
})
public static class Request {
#XmlAnyElement(lax = true)
#XmlElementRefs({
#XmlElementRef(name = "AirAvailability", type = AirAvailability.class)
})
protected Object any;
public Object getAny() {
return any;
}
public void setAny(Object value) {
this.any = value;
}
}
}
and I want to marshal it into this xml below:
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<soap:Envelope>
<soap:Body><SubmitXml>
<Profile>DynGalileoProd_7OQ7</Profile>
<Request>
<AirAvailability_12 xmlns=\"\">
<AirAvailMods>
<GenAvail>
<NumSeats>2</NumSeats>
<Class>Y</Class>
<StartDt>20151201</StartDt>
<StartPt>TPE</StartPt>
<EndPt>HKG</EndPt>
<StartTm><![CDATA[ ]]></StartTm>
</GenAvail>
</AirAvailMods>
</AirAvailability_12>
</Request>
<Filter><_ /></Filter>
</SubmitXml>
</soap:Body>
the problem is how can I generate such an element like <_ /> at element Filter?
another question is how can I generate element text like <![CDATA []]> at element <StartTm>? The characters < and > are always changed into < and >.
With this method:
<T> JAXBElement<T> wrap( String ns, String tag, T o ){
QName qtag = new QName( ns, tag );
Class<?> clazz = o.getClass();
#SuppressWarnings( "unchecked" )
JAXBElement<T> jbe = new JAXBElement( qtag, clazz, o );
return jbe;
}
it is possible to do
Filter filter = new Filter();
String s = "";
filter.setAny( wrap( "", "_", s ) );
and this will create
<Filter><_></_></Filter>
and since <_/> is, by definition, the same as <_></_>, you have what you want.
Your second request cannot fulfilled without writing your own XML writer. However, it is definitely unnecessary to do so. Using or not using <![CDATA []]> is a matter of convenience when editing XML manually. If the XML writer escapes < and > properly, there is no reason why CDATA should be used.

Why fasterxml lost the "xsi:type" attribute with JaxbAnnotationModule but JAXB Marshaller is fine

The original JAXB Marshaller works fine when I add the #XmlSeeAlso annotation to the abstract xsd classes.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Service xmlns="http://www.a.com">
<animal xsi:type="Dog" holder="Apache" name="Tomcat" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</Service>
When I turn to jackson(registered the JaxbAnnotationModule), however I got a different serialized string whose "xsi:type" tag is lost.
<Service xmlns="">
<animal holder="Apache" name="Tomcat"></animal>
</Service>
I've tried the #JsonTypeInfo annotation, but it doesn't work. How to fix
Here comes my example xsd entities,
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"animal"})
#XmlRootElement(name = "Service")
public class Service {
#XmlElement(name = "animal")
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Animal", propOrder = {"name"})
#XmlSeeAlso({Dog.class})
public abstract class Animal {
#XmlAttribute(name = "name", required = true)
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Dog", propOrder = {"holder"})
public class Dog extends Animal {
#XmlAttribute(name = "holder", required = true)
private String holder;
public String getHolder() {
return holder;
}
public void setHolder(String holder) {
this.holder = holder;
}
}
Test case,
#Test
public void testXsiType() throws Exception {
Service service = new Service();
Dog dog = new Dog();
service.setAnimal(dog);
dog.setName("Tomcat");
dog.setHolder("Apache");
JAXBContext jaxb = JAXBContext.newInstance(Service.class, Dog.class);
Marshaller marshaller = jaxb.createMarshaller();
StringWriter writer = new StringWriter();
marshaller.marshal(service, writer);
System.out.println(writer.toString());
ObjectMapper serializer = new XmlMapper();
serializer.registerModule(new JaxbAnnotationModule());
serializer.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
serializer.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
System.out.println(serializer.writeValueAsString(service));
}
lib I used,
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.4.5</version>
</dependency>

JAXB Reach Nested XmlElement Example

Here my XmlRoot class:
#XmlRootElement(name = "IGE")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "IGEType", propOrder = { "altin" })
public class IGEType {
#XmlElement(name = "ALTIN", required = true)
protected List<ALTINType> altin;
public List<ALTINType> getALTIN() {
if (altin == null) {
altin = new ArrayList<ALTINType>();
}
return this.altin;
}
}
Then successor(child) class of root :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ALTINType", propOrder = { "seanSytl" })
public class ALTINType {
#XmlElement(name = "SEANSytl", required = true)
protected SEANSytlType seanSytl;
}
At last, successor class of successor of root :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "SEANSytlType", propOrder = { "birim", "oncekiKapanis", "enDusuk", "enYuksek", "kapanis", "agirlikliOrtalama", "islemHacmi", "islemMiktari", "bicim", "gram", "islemSayisi" })
public class SEANSytlType {
#XmlElement(required = true)
protected String birim;
#XmlElement(name = "onceki_kapanis", required = true)
protected BigDecimal oncekiKapanis;
#XmlElement(name = "en_dusuk", required = true)
protected BigDecimal enDusuk;
#XmlElement(name = "en_yuksek", required = true)
protected BigDecimal enYuksek;
#XmlElement(required = true)
protected BigDecimal kapanis;
#XmlElement(name = "agirlikli_ortalama", required = true)
protected BigDecimal agirlikliOrtalama;
#XmlElement(name = "islem_hacmi", required = true)
protected BigDecimal islemHacmi;
#XmlElement(name = "islem_miktari", required = true)
protected BigDecimal islemMiktari;
#XmlElement(name = "BICIM", required = true)
protected BigDecimal bicim;
#XmlElement(name = "GRAM", required = true)
protected BigDecimal gram;
#XmlElement(name = "islem_sayisi")
protected int islemSayisi;
}
Myhandler class:
#Override
public void handleXMLtoIABData(RequestTcmbXMLData req) throws HmnServiceException {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(IGEType.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
File XMLfile = new File("C:\\Users\\U067944\\Desktop\\IAB_bülten.xml");
IGEType igeRoot = (IGEType) jaxbUnmarshaller.unmarshal(XMLfile);
**List<SEANSytlType> listofAltinYtl = (List<SEANSytlType>) ((List<ALTINType>) igeRoot.getALTIN()).getSEANSytl();**
for (SEANSytlType altinYtl : listofAltinYtl) {
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
In my handler class I try to reach last successor class (List SEANSytlType ), but it doesnt work.
I get this error :
jvmId: [300], transactionId:[3005624292568000] .Root Cause: [java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.ykb.hmn.mdt.marketdata.xmlparser.iab.ALTINType]
I also try this in handler but same:
IGEType igeRoot = (IGEType) jaxbUnmarshaller.unmarshal(XMLfile);
String inputDate = igeRoot.getIGEBULTENGUNTR().getGun2();
List<ALTINType> listAltinRoot = (List<ALTINType>) igeRoot.getALTIN();
List<SEANSytlType> listofAltinYtl = (List<SEANSytlType>) listAltinRoot.get(0);
Where am I wrong?
Thanks in advance!
Based your sample classes
IGEType
#XmlRootElement(name = "IGE")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "IGE", propOrder = { "altin" })
public class IGEType {
#XmlElement(name = "Altin", required = true)
public List<ALTINType> altin;
public List<ALTINType> getALTIN() {
if (altin == null) {
altin = new ArrayList<ALTINType>();
}
return this.altin;
}
}
Then ALTINType
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "altin", propOrder = { "seanSytl" })
public class ALTINType {
#XmlElement(name = "SEANSytl", required = true)
protected SEANSytlType seanSytl;
}
Then SEANSytlType
<!-- language: java -->
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "SEANSytl", propOrder = { "birim"})
public class SEANSytlType {
#XmlElement(required = true)
protected String birim;
}
Then sample class for test
<!-- language: java -->
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
JAXBContext jaxbContext = JAXBContext.newInstance(IGEType.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
File XMLfile = new File("sample1.xml");
IGEType igeRoot = (IGEType) jaxbUnmarshaller.unmarshal(XMLfile);
List<ALTINType> listAltinRoot = igeRoot.getALTIN();
// here you ll be have error ///
// List<SEANSytlType> listofAltinYtl = (List<SEANSytlType>) listAltinRoot.get(0);
//
// for (SEANSytlType altinYtl : listofAltinYtl) {
// System.out.println(altinYtl.birim);
// }
} catch (JAXBException e) {
e.printStackTrace();
}
}
So and and end sample xml
<?xml version="1.0" encoding="UTF-8"?>
<IGE>
<Altin>
<SEANSytl>
<birim>cccc</birim>
</SEANSytl>
</Altin>
<Altin>
<SEANSytl>
<birim>dddd</birim>
</SEANSytl>
</Altin>
</IGE>
So basicly problem was that you have in root (IGE) childs list altin but in altin object thest is only 1 child object seansylt not at list like you have in altin so fix altin object add list there and take look at my example

Categories