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

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.

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>

Convert Soap XML response to Object Java with JAXB

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

JAXB anyType fails to cast

The following code is resulting in a cast exception and I'm not sure why. Objects in ParameterValueList should be eagerly unmarshalled to the JAXB object ParameterValueStruct, but it's not. Everything was generated directly from the soap encoding and cwmp schema files.
Does anyone have any suggestions?
public static void main(String[] args) throws JAXBException, FileNotFoundException
{
JAXBContext c = JAXBContext.newInstance("org.dslforum.cwmp_1_1");
Unmarshaller u = c.createUnmarshaller();
Inform inform = (Inform) u.unmarshal(new FileInputStream("test.xml"));
List<Object> list = inform.getParameterList().getAny();
System.out.println(list); // prints [[ParameterValueStruct: null], ...
for (Object o : list) {
ParameterValueStruct pv = (ParameterValueStruct)o; // exception here
System.out.println(pv.getName());
}
}
Exception in thread "main" java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to org.dslforum.cwmp_1_1.ParameterValueStruct
at Test.main(Test.java:26)
I have this class which was generated from http://schemas.xmlsoap.org/soap/encoding/ using Java's xjc tool:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Array", propOrder = {
"any"
})
#XmlSeeAlso({
ParameterValueList.class,
})
public class Array {
#XmlAnyElement(lax = true)
protected List<Object> any;
#XmlAttribute(name = "id")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlID
#XmlSchemaType(name = "ID")
protected java.lang.String id;
#XmlAttribute(name = "href")
#XmlSchemaType(name = "anyURI")
protected java.lang.String href;
#XmlAttribute(name = "arrayType", namespace = "http://schemas.xmlsoap.org/soap/encoding/")
protected java.lang.String arrayType;
#XmlAttribute(name = "offset", namespace = "http://schemas.xmlsoap.org/soap/encoding/")
protected java.lang.String offset;
#XmlAnyAttribute
private Map<QName, java.lang.String> otherAttributes = new HashMap<QName, java.lang.String>();
public List<Object> getAny() {
if (any == null) {
any = new ArrayList<Object>();
}
return this.any;
}
....
}
I also have these 2 classes which were also generated via the same tool, but from https://www.broadband-forum.org/cwmp/cwmp-1-1.xsd:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ParameterValueList")
public class ParameterValueList
extends Array
{
}
Second file:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ParameterValueStruct", propOrder = {
"name",
"value"
})
public class ParameterValueStruct {
#XmlElement(name = "Name", required = true)
protected String name;
#XmlElement(name = "Value", required = true)
#XmlSchemaType(name = "anySimpleType")
protected Object value;
...
}
And here is my test.xml file:
<?xml version="1.0"?>
<cwmp:Inform xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:cwmp="urn:dslforum-org:cwmp-1-1" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ParameterList soap-enc:arrayType="cwmp:ParameterValueStruct[3]">
<ParameterValueStruct>
<Name>Device.DHCPv4.ClientNumberOfEntries</Name>
<Value xsi:type="xsd:unsignedInt">0</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.DNS.Client.ServerNumberOfEntries</Name>
<Value xsi:type="xsd:unsignedInt">1</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.DeviceInfo.AdditionalSoftwareVersion</Name>
<Value xsi:type="xsd:string">DM: 532,SK: 2.6.33.9-rt31,SF: 251X 137.0,BK: 10</Value>
</ParameterValueStruct>
</ParameterList>
</cwmp:Inform>
You just have to add #XmlRootElement(name="ParameterValueStruct",namespace="") in front of ParameterValueStruct
Here you need explicit namespace="" becauce of the package-info.java
#javax.xml.bind.annotation.XmlSchema(namespace = "urn:dslforum-org:cwmp-1-1")
package org.dslforum.cwmp_1_1;
The correct class should look like this:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ParameterValueStruct", propOrder = {
"name",
"value"
})
#XmlRootElement(name="ParameterValueStruct",namespace="")
public class ParameterValueStruct {
#XmlElement(name = "Name", required = true)
protected String name;
#XmlElement(name = "Value", required = true)
#XmlSchemaType(name = "anySimpleType")
protected Object value;
...
}
PS: See this http://blog.bdoughan.com/2012/12/jaxbs-xmlanyelementlaxtrue-explained.html for a better JAXB-tutorial about #XmlAnyElement(lax=true)

How do I dynamically add #XmlRoot tag from java?

I have a JAXB generated classes.The root tag class is Foo which is given below.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"input"
})
#XmlRootElement(name = "Foo")
public class Foo {
#XmlElement(name = "Input", required = true)
protected Too input;
public Too getInput() {
return input;
}
public void setInput(Too value) {
this.input = value;
}
}
There is a sub tag class as below.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Bar", propOrder = {
"request"
})
public class Bar {
#XmlElement(name = "Request", required = true)
protected List<RequestType> request;
public List<RequestType> getRequest() {
if (request == null) {
request = new ArrayList<RequestType>();
}
return this.request;
}
}
There are some case where I need to construct an xml with Bar as a root class. I use Jaxb marshallar to convert from the object to string.
public static String jaxbObjectToXMLString(Object obj) {
try {
final Marshaller m = JAXBContext.newInstance(obj.getClass()).createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
final StringWriter w = new StringWriter();
m.marshal(obj, w);
return w.toString();
} catch (JAXBException e) {
logger.error("Returning empty xml string", e);
return EMPTY_STR;
}
}
I can able to marshal If I mention #XmlRootElement(name = "Bar"). I dont want to add this in the class as I dont want Bar to be my root tag always. Is there a way that I can do this inside jaxbObjectToXMLString(Object obj) based on the object I am passing.
if(obj instanceof Bar) { dynamically make bar as XmlRoot and generate xml}
else if(obj instanceof Foo){ marshall as it is}
The usual way is to define more than one xs:element in your XML Schema and compile again (xjc).
<xs:element name="Foo" type="Foo" />
<xs:element name="Bar" type="Bar" />
There is no problem with #XmlRootElement being on two classes.
It's also possible to define a root element wrapped into a JAXBElement:
<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;
}
void marshal() throws Exception {
Foo foo = new Foo();
//...
JAXBElement<Foo> jbe = wrap( "", "Foo", foo );
JAXBContext jc = JAXBContext.newInstance( PACKAGE );
Marshaller m = jc.createMarshaller();
m.marshal( jbe, ... );
}

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);
}
}

Categories