XJC - JAXB Annotations in command line - java

I'm currently working on generating Java classes from XSD files.
I created an XSD file using restrictions.
As example heredown, I want to parse a date in a specific format MMYY.
Example:
<xsd:element name="dummyDate" minOccurs="0">
<xsd:simpleType>
<xsd:restriction base="xsd:date">
<xsd:pattern value="MMYY" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
However, the generated class doesn't contain/import the restriction.
protected XMLGregorianCalendar dummyDate;
/**
* Gets the value of the dummyDate property.
*
* #return
* possible object is
* {#link XMLGregorianCalendar }
*
*/
public XMLGregorianCalendar getdummyDate() {
return dummyDate;
}
/**
* Sets the value of the dummyDate property.
*
* #param value
* allowed object is
* {#link XMLGregorianCalendar }
*
*/
public void setdummyDate(XMLGregorianCalendar value) {
this.dummyDate= value;
}
Since I'm blocked with this issue, I'm having the two following questions:
What would be the best way to proceed in order to enable those
restriction while parsing?
How to implement it?
HINTS:
JAXB Bindings [https://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/tutorial/doc/JAXBUsing4.html]
krasa-jaxb-tools [https://github.com/krasa/krasa-jaxb-tools]
Update
So I created I binding file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings>
<xjc:simple />
<xjc:serializable uid="-1" />
<jaxb:javaType name="java.util.Date" xmlType="xs:date"
parseMethod="general.CalendarFormatConverter.parseDate"
printMethod="general.CalendarFormatConverter.printDate" />
</jaxb:globalBindings>
</jaxb:bindings>
The CalendarFormatConverter.java:
package general;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CalendarFormatConverter {
/**
* Calendar to custom format print to XML.
*
* #param val
* #return
*/
public static Date parseDate(String val) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMYY");
Date date = null;
try {
date = simpleDateFormat.parse(val);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return date;
}
/**
* Date to custom format print to XML.
*
* #param val
* #return
*/
public static String printDate(Date val) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMYY");
return simpleDateFormat.format(val);
}
}
So I can convert now, but the format of the date isn't matching the restrinction...

Related

Remove <return> element from soap response - JaxWs

I have the following Classes, I'm basically re-writing some existing services and had to use 'wsimport' to generate the following classes from the wsdl. The Soap response has to be exactly similar to how it used to return in the legacy code. The following is the generated classes from the import.
Somehow the <return> element got added to the soap response, I've checked my classes and I do not see that anywhere in the imports that were generated. Any idea on how to remove these?
I looked at this solution here Remove element <return> in JAX-WS SOAP Response but it is not ideal for me.
package org.openuri;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import net.tds.msa.address.addressvalues.Values;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element ref="{http://xx.net/msa/Address/AddressValues.xsd}AddressValuesResponse"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"addressValuesResponse"
})
#XmlRootElement(name = "getPostDirectionalResponse")
public class GetPostDirectionalResponse {
#XmlElement(name = "AddressValuesResponse", namespace = "http://xx.net/msa/Address/AddressValues.xsd", required = true)
protected Values addressValuesResponse;
/**
* Gets the value of the addressValuesResponse property.
*
* #return
* possible object is
* {#link Values }
*
*/
public Values getAddressValuesResponse() {
return addressValuesResponse;
}
/**
* Sets the value of the addressValuesResponse property.
*
* #param value
* allowed object is
* {#link Values }
*
*/
public void setAddressValuesResponse(Values value) {
this.addressValuesResponse = value;
}
}
and
package net.xx.msa.address.addressvalues;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for values complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="values">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="AddressValue" type="{http://xx.net/msa/Address/AddressValues.xsd}AddressValue" maxOccurs="unbounded" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "values", propOrder = {
"addressValue"
})
public class Values {
#XmlElement(name = "AddressValue")
protected List<AddressValue> addressValue;
/**
* Gets the value of the addressValue property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the addressValue property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getAddressValue().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link AddressValue }
*
*
*/
public List<AddressValue> getAddressValue() {
if (addressValue == null) {
addressValue = new ArrayList<AddressValue>();
}
return this.addressValue;
}
}
Response is where <return> element is added. How do I remove this without using soap handler in jaxws?
<ns3:getPostDirectionalResponse xmlns:ns2="http://xx.net/msa/Address/AddressValues.xsd" xmlns:ns3="http://www.openuri.org/">
<return>
<ns2:AddressValuesResponse>
<ns2:AddressValue>
<ns2:value>South</ns2:value>
<ns2:valueAbbrev>S</ns2:valueAbbrev>
</ns2:AddressValuesResponse>
</return>
</ns3:getPostDirectionalResponse>
In your service endpoint interface, add #SOAPBinding(parameterStyle=ParameterStyle.BARE) to your #WebMethod:
package org.openuri;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.ParameterStyle;
#WebService
public interface ExampleService {
#WebMethod
#SOAPBinding(parameterStyle=ParameterStyle.BARE)
GetPostDirectionalResponse getPostDirectional(String input);
}
This changes the generated schema (for me) for getPostDirectionalResponse element to:
<xs:element name="getPostDirectionalResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="AddressValuesResponse" type="tns:values" form="qualified"/>
</xs:sequence>
</xs:complexType>
</xs:element>
and the resultant soap response is bare (unwrapped, no <return>):
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns3:getPostDirectionalResponse xmlns:ns2="http://xx.net/msa/Address/AddressValues.xsd" xmlns:ns3="http://openuri.org/">
<ns2:AddressValuesResponse>
<AddressValue>hello</AddressValue>
</ns2:AddressValuesResponse>
</ns3:getPostDirectionalResponse>
</S:Body>
</S:Envelope>
However, BARE comes with a constraint - the service operation can only have one argument/input.
Hi i had the same problem and my solution was:
in the webservice file
#WebService(serviceName = "MyService")
public class MyService{
#WebResult(header = true, name = "ResponseLastWrapperElement", targetNamespace = "")
//the contain of the service
I hope this works for more people!!!

Change xjc generated Java field name from 'value' to 'name'

I'm working on a XML schema and I'd like to change the name of the field in the generated class from 'value' to 'name'. Here is what I would like my StackOverflow.xsd file to look like:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:StackOverflow="http://stackoverflow.com"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
targetNamespace="http://stackoverflow.com"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
jaxb:version="2.1">
<element name="toolbar">
<complexType>
<sequence>
<element name="action" type="StackOverflow:action" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute type="string" name="id" use="required"/>
</complexType>
</element>
<simpleType name="actionName">
<restriction base="string">
<enumeration value="Start"/>
<enumeration value="Stop"/>
<enumeration value="Cancel"/>
</restriction>
</simpleType>
<complexType name="action">
<simpleContent>
<extension base="StackOverflow:actionName">
<annotation>
<appinfo>
<!--This ensures that the field in the Action class will be called 'name' rather than 'value'-->
<jaxb:property name="name"/>
</appinfo>
</annotation>
<attribute name="isActive" type="boolean" default="false"/>
</extension>
</simpleContent>
</complexType>
</schema>
As you can see I've tried to add a jaxb:property to change the name of the field 'value' to 'name', but XJC is complaining that "Specified property customization is not used". Here is the command I ran
$ xjc StackOverflow.xsd -d tmp/
parsing a schema...
[ERROR] Specified property customization is not used.
line 33 of file:/D:/dev/workspace-action-engine/jris/jris/branches/action-engine/client/com.agfa.ris.client.lta/src/main/resources/com/agfa/ris/client/lta/listarea/controller/actionsmodel/StackOverflow.xsd
Failed to parse a schema.
If I remove this section from the XSD file:
<annotation>
<appinfo>
<!--This ensures that the field in the Action class will be called 'name' rather than 'value'-->
<jaxb:property name="name"/>
</appinfo>
</annotation>
, then this is the Action.java file that is created
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2015.05.20 at 09:05:26 AM CEST
//
package com.stackoverflow;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
/**
* <p>Java class for action complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="action">
* <simpleContent>
* <extension base="<http://stackoverflow.com>actionName">
* <attribute name="isActive" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
* </extension>
* </simpleContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "action", propOrder = {
"value"
})
public class Action {
#XmlValue
protected ActionName value;
#XmlAttribute(name = "isActive")
protected Boolean isActive;
/**
* Gets the value of the value property.
*
* #return
* possible object is
* {#link ActionName }
*
*/
public ActionName getValue() {
return value;
}
/**
* Sets the value of the value property.
*
* #param value
* allowed object is
* {#link ActionName }
*
*/
public void setValue(ActionName value) {
this.value = value;
}
/**
* Gets the value of the isActive property.
*
* #return
* possible object is
* {#link Boolean }
*
*/
public boolean isIsActive() {
if (isActive == null) {
return false;
} else {
return isActive;
}
}
/**
* Sets the value of the isActive property.
*
* #param value
* allowed object is
* {#link Boolean }
*
*/
public void setIsActive(Boolean value) {
this.isActive = value;
}
}
As you can see the #XmlValue field is called 'value', but I would prefer that it be called 'name' or 'actionName', but I can't figure out how to do that. I'd appreciate any help someone can provide.
Thanks

JAXB getting Object "" is found in an IDREF property but this object doesnt have an ID

Here is a test case using a file from SCORM for imsmanifest,xml. This XML has been in use for about 5 or more years, and being a standard I don't want to change it unless required to get this to work.
You can find the xsd file here
The error occurs between <organizations default="CYBER4.ORG"> and <organization identifier="CYBER4.ORG">
In my project, this is the entry from my pom.xml for my jaxb version
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.11</version>
</dependency>
to generate the Java code I ran (this is the install of xjc for Ubuntu 14.04)
$ xjc -version
xjc 2.2.4-2
$ xjc -verbose -p org.cyber4.scorm2004.xml.manifest.imscp imscp_v1p2.xsd
The output generates (amongst other things)
public class OrganizationsType {
#XmlAttribute(name = "default")
#XmlIDREF
#XmlSchemaType(name = "IDREF")
protected Object _default;
}
and
public class OrganizationType {
#XmlAttribute(name = "identifier", required = true)
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlID
#XmlSchemaType(name = "ID")
protected String identifier;
}
This is the test code
package org.cyber4.scorm2004.build;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.cyber4.scorm2004.xml.manifest.imscp.ManifestMetadataType;
import org.cyber4.scorm2004.xml.manifest.imscp.ManifestType;
import org.cyber4.scorm2004.xml.manifest.imscp.ObjectFactory;
import org.cyber4.scorm2004.xml.manifest.imscp.OrganizationType;
import org.cyber4.scorm2004.xml.manifest.imscp.OrganizationsType;
import org.cyber4.scorm2004.xml.manifest.imscp.ResourcesType;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
public class TestSCORMBuilder {
public static void main(String args[]) {
try {
ObjectFactory objectFactory = new ObjectFactory();
/*
* <metadata />
*/
ManifestMetadataType metadataType = objectFactory.createManifestMetadataType();
/*
* <organizations default="CYBER4.ORG">
* <organization identifier="CYBER4.ORG" />
* </organizations>
*/
// https://java.net/jira/browse/JAXB-872
OrganizationsType organizationsType = objectFactory.createOrganizationsType();
organizationsType.setDefault("CYBER4.ORG");
OrganizationType organizationType = objectFactory.createOrganizationType();
organizationType.setIdentifier("CYBER4.ORG");
organizationsType.getOrganization().add(organizationType);
/*
* <resources />
*/
ResourcesType resourcesType = objectFactory.createResourcesType();
/*
* <manifest>
* <metadata/ >
* <organizations default="CYBER4.ORG">
* <organization identifier="CYBER4.ORG" />
* </organizations>
* <resources />
* <manifest>
*/
ManifestType manifestType = objectFactory.createManifestType();
manifestType.setMetadata(metadataType);
manifestType.setOrganizations(organizationsType);
manifestType.setResources(resourcesType);
JAXBContext context = JAXBContext.newInstance("org.cyber4.scorm2004.xml.manifest.imscp");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,
"http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd");
marshaller.marshal(objectFactory.createManifest(manifestType), System.out);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
When I run the code I get this error
javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: Object "CYBER4.ORG" is found in an IDREF property but this object doesnt have an ID.]
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95)
at org.cyber4.scorm2004.build.TestSCORMBuilder.main(TestSCORMBuilder.java:73)
Caused by: com.sun.istack.internal.SAXException2: Object "CYBER4.ORG" is found in an IDREF property but this object doesnt have an ID.
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:237)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.errorMissingId(XMLSerializer.java:1045)
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$IDREFTransducedAccessorImpl.print(TransducedAccessor.java:275)
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$IDREFTransducedAccessorImpl.print(TransducedAccessor.java:254)
at com.sun.xml.internal.bind.v2.runtime.property.AttributeProperty.serializeAttributes(AttributeProperty.java:86)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeAttributes(ClassBeanInfoImpl.java:360)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:678)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:145)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:115)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:317)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:324)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:60)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
... 3 more
If I comment out line 37
organizationsType.setDefault("CYBER4.ORG");
it generates this XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd">
<metadata/>
<organizations>
<organization identifier="CYBER4.ORG"/>
</organizations>
<resources/>
</manifest>
but it's missing the
default="CYBER4.ORG"
in <organizations> which is required for imsmanifest.xml to be valid.
This looks like this bug but I want to be sure I haven't missed anything.
default should not contain the id of the object you want to reference, but an object with the same id than the object you want to reference.
Try to replace :
organizationsType.setDefault("CYBER4.ORG");
with :
OrganizationType o = new OrganizationType()
o.setIdentifier("CYBER4.ORG");
organizationsType.setDefault(o);
If organizationType has already been set you can maybe also try :
organizationsType.setDefault(organizationType);

JAXB Bindings File Sets #XmlElement type to String instead of XMLGregorianCalendar

I'm trying to create an XmlAdapter that takes in an XMLGregorianCalendar and outputs an XMLGregorianCalendar. The purpose is simlply to remove timezone data from the element when unmarshalling data.
It looks like this:
public class TimezoneRemoverAdapter extends XmlAdapter<XMLGregorianCalendar, XMLGregorianCalendar> {
public XMLGregorianCalendar unmarshal(XMLGregorianCalendar xgc) {
if(xgc == null) {
return null;
}
xgc.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
return xgc;
}
public XMLGregorianCalendar marshal(XMLGregorianCalendar xgc) {
return xgc;
}
}
This works fine for the following code:
public class FooElement {
#XmlElement(name="bar-date")
#XmlJavaTypeAdapter(TimezoneRemoverAdapter.class)
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar barDate;
}
Unfortunately, when I generate the code using a jaxb-bindings.xml file, the above code looks like this:
public class FooElement {
#XmlElement(name="bar-date", type=java.lang.String.class)
#XmlJavaTypeAdapter(TimezoneRemoverAdapter.class)
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar barDate;
}
It sets the type to String, so my above method doesn't work. The type String setting is overriding the XMLGregorianCalendar type that it should be. I can manually change it, but I'd rather not have to remember to update it every time the jaxb files are regenerated. Does anyone know if there's an option to manually set the #XmlElement type or have it ignored?
Here is the relevant portion of the jaxb-bindings.xml file:
<jxb:bindings node=".//xs:element[#name=bar-date]">
<jxb:property>
<jxb:baseType>
<jxb:javaType name="javax.xml.datatype.XMLGregorianCalendar" adapter="foo.bar.TimezoneRemoverAdapter" />
</jxb:baseType>
</jxb:property>
</jxb:bindings>
UPDATE
summarizing:
you have a schema that uses date style somewhere, and you cannot change the schema
you have some XML data that uses that schema and specify some date with timezone (so it's yyyy-MM-ddXXX format)
you want to remove the XXX part from the representation of the date in that file (date itself does not ship any timezone, date is just a number)
so this could be a sample schema:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<element name="foo">
<complexType>
<sequence>
<element name="bar" type="date" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
</element>
</schema>
this could be a sample data:
<?xml version="1.0" encoding="UTF-8"?>
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="foo.xsd">
<bar>2014-01-01+06:00</bar>
</foo>
this is JAXB annotated class
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Foo implements Serializable
{
private static final long serialVersionUID = 1L;
#XmlElement(name = "bar")
#XmlJavaTypeAdapter(DateAdapter.class)
#XmlSchemaType(name = "date")
private Date bar;
// getters/setters
}
this is date adapter
public class DateAdapter extends XmlAdapter<String, Date>
{
#Override
public String marshal(Date date)
{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return df.format(date);
}
#Override
public Date unmarshal(String date) throws ParseException
{
DateFormat df = new SimpleDateFormat("yyyy-MM-ddXXX");
return df.parse(date);
}
}
this is the main, validating against the schema:
public static void main(String[] args) throws JAXBException, SAXException
{
JAXBContext context = JAXBContext.newInstance(Foo.class);
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(Foo.class.getResource("/foo.xsd"));
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(schema);
Foo foo = (Foo) unmarshaller.unmarshal(Foo.class.getResource("/foo.xml"));
System.out.println("unmarshalled: " + foo.getBar());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "foo.xsd");
marshaller.setSchema(schema);
marshaller.marshal(foo, System.out);
}
and this is the output, timezone has been removed and date representation has obviously changed
unmarshalled: Tue Dec 31 19:00:00 CET 2013
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="foo.xsd">
<bar>2013-12-31</bar>
</foo>
maybe this date representation change is not what you'd expect, but this is not a JAXB concern, the date represented has not changed.
i was forgetting the bindings to reverse generate Foo:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.0">
<jaxb:globalBindings>
<xjc:javaType name="java.util.Date" xmlType="xsd:date" adapter="aaa.DateAdapter" />
</jaxb:globalBindings>
</jaxb:bindings>
END OF UPDATE
sorry, too long for a comment...
i can't understand:
why the hell are you using XmlGregorianCalendar?
why should you marshal/unmarshal (serialize/deserialize) to the very same data structure?
why should you remove timezone??
and
i use straight and simple java.util.Date
marshal/unmarshal should always involve Strings (at least for XML)
i really don' see a good reason to arbitrarily remove a piece of a date representation. maybe you want to serialize it in an absolute way.
however
public class DateAdapter extends XmlAdapter<String, Date>
{
#Override
public String marshal(Date date)
{
DateFormat df = DateFormat.getDateTimeInstance();
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return df.format(date);
}
#Override
public Date unmarshal(String date) throws ParseException
{
DateFormat df = DateFormat.getDateTimeInstance();
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return df.parse(date);
}
public static void main(String[] args) throws ParseException
{
DateAdapter adapter = new DateAdapter();
String str = adapter.marshal(new Date());
System.out.println(str); // 16-dic-2013 10.02.09 --> to gmt
Date date = adapter.unmarshal(str);
System.out.println(date); // Mon Dec 16 11:02:09 CET 2013 --> correct, i'm gmt+1
}
}
You have to specify the java type differently, in your case:
<jxb:javaType
name="javax.xml.datatype.XMLGregorianCalendar"
xmlType="xs:date"
printMethod="foo.bar.TimezoneRemoverAdapter.marshall"
parseMethod="foo.bar.TimezoneRemoverAdapter.unmarshall"
/>
It works fine for me and I did something similar with more adapters:
<jaxb:globalBindings>
<xjc:serializable uid="12343" />
<jaxb:javaType name="java.util.Date" xmlType="xs:date" printMethod="com.foo.DateAdapter.printDate" parseMethod="com.foo.DateAdapter.parseDate" />
<jaxb:javaType name="java.util.Date" xmlType="xs:dateTime" printMethod="com.foo.DateAdapter.printDate" parseMethod="com.foo.DateAdapter.parseDate" />
<jaxb:javaType name="java.util.Date" xmlType="xs:time" printMethod="com.foo.TimeAdapter.printTime" parseMethod="com.foo.TimeAdapter.parseTime" />
</jaxb:globalBindings>
I put the above bindings as a globalBindings in a different file with .xjb extension and I use it everywhere I need it.

How to read an xs:any response using CXF Generated Client?

When consuming a webserice with CXF 2.1.4 (the generated client) I am having problem getting the response based on the following XSD snippet in the WSDL. CXF Generates a List representing it, but when I execute the service, the response comes null. I used wireshark to what I was reciving and indeed the response XMl is coming as expected, but CXF just give me null object. The exposed services is implemented using .NET.
Below the XSD of the response object. And
<!--- chunk -->
<s:element name="GestionSIIFResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GestionSIIFResult">
<s:complexType mixed="true">
<s:sequence>
<s:any />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
<!--- chunk -->
And this is the response I am getting from the service:
<soap:Body>
<GestionSIIFResponse xmlns="http://tempuri.org/">
<GestionSIIFResult>
<Siif xmlns="">
<Pagina>NUY001B</Pagina>
<Exitos>
<ExitoRep>
<CodExito>SIL0082</CodExito>
<DesExito>La transaccion se ha aplicado satisfactoriamente</DesExito>
</ExitoRep>
</Exitos>
<InformacionCab/>
<Repeticiones/>
</Siif>
</GestionSIIFResult>
</GestionSIIFResponse>
Below is the Generated java class that should "hold" the response from the web service
/*
* some imports here
*/
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="GestionSIIFResult" minOccurs="0">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <any/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </element>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"gestionSIIFResult"
})
#XmlRootElement(name = "GestionSIIFResponse")
public class GestionSIIFResponse {
#XmlElement(name = "GestionSIIFResult")
protected GestionSIIFResponse.GestionSIIFResult gestionSIIFResult;
/**
* Gets the value of the gestionSIIFResult property.
*
* #return
* possible object is
* {#link GestionSIIFResponse.GestionSIIFResult }
*
*/
public GestionSIIFResponse.GestionSIIFResult getGestionSIIFResult() {
return gestionSIIFResult;
}
/**
* Sets the value of the gestionSIIFResult property.
*
* #param value
* allowed object is
* {#link GestionSIIFResponse.GestionSIIFResult }
*
*/
public void setGestionSIIFResult(GestionSIIFResponse.GestionSIIFResult value) {
this.gestionSIIFResult = value;
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <any/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"content"
})
public static class GestionSIIFResult {
#XmlMixed
#XmlAnyElement(lax = true)
protected List<Object> content;
/**
* Gets the value of the content property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the content property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getContent().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link Object }
* {#link String }
*
*
*/
public List<Object> getContent() {
if (content == null) {
content = new ArrayList<Object>();
}
return this.content;
}
}
}
Below the generated proxy port
/**
* This class was generated by Apache CXF 2.1.4
* Mon Jan 17 12:02:39 COT 2011
* Generated source version: 2.1.4
*
*/
#WebService(targetNamespace = "http://tempuri.org/", name = "WSGYG05Soap")
#XmlSeeAlso({ObjectFactory.class})
public interface WSGYG05Soap {
#ResponseWrapper(localName = "GestionSIIFResponse", targetNamespace = "http://tempuri.org/", className = "suramericana.banw.servicios.tuya.v2.GestionSIIFResponse"/*"org.tempuri.GestionSIIFResponse"*/)
#RequestWrapper(localName = "GestionSIIF", targetNamespace = "http://tempuri.org/", className = "suramericana.banw.servicios.tuya.v2.GestionSIIF"/*"org.tempuri.GestionSIIF"*/)
#WebResult(name = "GestionSIIFResult", targetNamespace = "http://tempuri.org/")
#WebMethod(operationName = "GestionSIIF", action = "http://tempuri.org/GestionSIIF")
public GestionSIIFResponse.GestionSIIFResult gestionSIIF(
#WebParam(name = "Peticion", targetNamespace = "http://tempuri.org/")
GestionSIIF.Peticion peticion,
#WebParam(header = true,name="CabAut", targetNamespace = "http://tempuri.org/")
CabAut cabAut
);
//#ResponseWrapper(localName = "GestionSIIFResponse", targetNamespace = "http://tempuri.org/", className = "suramericana.banw.servicios.tuya.v2.GestionSIIFResponse"/*"org.tempuri.GestionSIIFResponse"*/)
//#RequestWrapper(localName = "GestionSIIF", targetNamespace = "http://tempuri.org/", className = "suramericana.banw.servicios.tuya.v2.GestionSIIF"/*"org.tempuri.GestionSIIF"*/)
//#WebResult(name = "GestionSIIFResult", targetNamespace = "http://tempuri.org/")
//#WebMethod(operationName = "GestionSIIF", action = "http://tempuri.org/GestionSIIF")
/*public GestionSIIFResponse.GestionSIIFResult gestionSIIF(
#WebParam(name = "Peticion", targetNamespace = "http://tempuri.org/")
GestionSIIF.Peticion peticion,
#WebParam(header = true,name="CabAut", targetNamespace = "http://tempuri.org/")
CabAut cabAut
);*/
}
The List returned by getContent() could potentially contains a variety of org.w3c.dom.Element, JAXBElement, or fully-bound classes.
If the JAXB context doesn't recognise the <Siif> element, then JAXB will play it safe and populate the list with a single Element object representing the <Siif> and its children. If it does recognise them , it'll either contain JAXBElementwhich in turn contains aSiifobject, or it may contain theSiif` object directly.
Java cannot express this variety in its types, so just binds to List<Object>.

Categories