We get the WSDLs from our customer. (I.e., we can't change them.)
The definition of one of the types looks something like this:
<complexType name="Type1">
<complexContent>
<restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
<sequence>
<element name="value" minOccurs="0">
<complexType>
<complexContent>
<restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
<choice>
<element name="bigdecimal" type="{http://www.w3.org/2001/XMLSchema}double"/>
<element name="date" type="{http://www.w3.org/2001/XMLSchema}date"/>
<element name="string" type="{http://www.w3.org/2001/XMLSchema}string"/>
</choice>
</restriction>
</complexContent>
</complexType>
</element>
<element name="element2" type="{http://www.w3.org/2001/XMLSchema}integer" minOccurs="0"/>
</sequence>
</restriction>
</complexContent>
</complexType>
resulting in things like
public void setBigdecimal(Double value) {
this.bigdecimal = value;
}
Now when we send a request with this type in it, it will generate something like this:
<rpcOp:value>
<rpcOp:bigdecimal>10.0</rpcOp:bigdecimal> <!-- IN SPITE OF THE NAME, THIS IS A DOUBLE VALUE! -->
<rpcOp:string>N</rpcOp:string>
</rpcOp:value>
The customer wants the content of to be shown without decimal digits, i.e., 10 etc.
I suspect that when generating the request xml from the Java objects, the JAX-WS framework simply calls Double.toString(), which will inevitably add a decimal point and a decimal digit.
Is there a way to change this without being able to modify the WSDL? Register some custom number formatter for this type or something like this?
Thanks!
In the meantime I found a solution. It looks something like this: (using JAXB)
xjc-serializable.xml :
...
<jaxb:globalBindings>
<xjc:serializable />
<!-- ADDED THIS: -->
<xjc:javaType name="java.lang.Double" xmlType="xs:double"
adapter="util.MyDoubleAdapter" />
</jaxb:globalBindings>
...
Then the java class:
public class MyDoubleAdapter extends XmlAdapter<String, Double> {
#Override
public String marshal(Double doubleValue) throws Exception {
if (doubleValue == null) {
return null;
}
String string = doubleValue.toString();
if (string.endsWith(".0")) {
string = string.replaceAll("\\.0", "");
}
return string;
}
public Double unmarshal(String stringValue) throws Exception {
if (stringValue == null) {
return null;
}
return Double.valueOf(stringValue);
}
}
And there you go.
Related
I have searched for this in Internet but unable to find a answer.
I am new to SOAP services, If I am wrong at any point please correct me. I was trying to generate Java classes from wsdl using command line tool ** JAX-WS RI wsimport**. I was able to generate all Request and Response classes.
The ObjectFactory.java generated from wsdl was missing most of the methods.
employee.wsdl.jaxb.bnd.xml
<jaxb:bindings version="2.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb/xjc">
<jaxb:bindings>
<jaxb:globalBindings generateElementProperty="false">
<xjc:serializable>
</jaxb:globalBindings>
</jaxb:bindings>
</jaxb:bindings>
employee.wsdl.bnd.xml
<jaxws:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
wsdlLocation="../sp.wsdl">
<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
</jaxws:bindings>
In jaxb.bnd.xml
While trying with <jaxb:globalBindings generateElementProperty="true"> Its able to generate all of the factory methods. But it was using JAXBElement<> wrapper for primititve data types like String,int,Long
While trying with <jaxb:globalBindings generateElementProperty="fasle"> Its able to generate the class without JAXBElement<> wrapper, but missing most of the factory methods.
cmd: wsimport META-INF/wsdl/employee.wsdl -keep -b META-INF/wsdl/bindings/employee.bnd.xml -b META-INF/wsdl/bindings/employee.jaxb.bnd.xml -wsdllocation META-INF/wsdl/employee.wsdl
Sample ObjectFactory.java
package xyz;
#XmlRegistry
class ObjectFactory {
private final static Qname _EmpDetailsSpecialEmpDetail_QNAME = new QName("", "scheduleEmp");
#XmlElementDecl(namespce = "", name="specialEmployee", scope= EmpDetails.class)
public SpecialEmpDetail EmpDetailsSpecialEmployee(SpecialEmpDetail value) {
return new SpecialEmpDetail(_EmpDetailsSpecialEmpDetail_QNAME, SpecialEmpDetail.class, EmpDetail.class, value);
}
EmpDetail.java
public class EmpDetail implements Serializable {
#XmlElementRef(name= "specialEmployee", required=false)
protected SpecialEmpDetail specialEmployee;
public SpcialEmpDetail getSpecialEmployee() {
return specialEmployee;
}
public SpcialEmpDetail setSpecialEmployee(SpcialEmpDetail value) {
this.specialEmployee = value;
}
}
SpecialEmpDetail.java
public class SpecialEmpDetail {
//local var
//getter and setter
.....
}
employee.wsdl
<?xml version="1.0" encoding="UTF-8">
<definitions name="psp"
targetNamespace="http://www.namespace.com/employee.wsdl"
.....
/>
<types>
<schmea targerNamespace = "http://www.namespace.com/employee.wsdl"
xmlns:SOAP-ENV = "http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi = "http://www.w3.org/2003/05/XMLSchema-instance"
xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
xmlns:emp = "http://www.namespace.com/employee/employee.xsd1"
<import namespace="http://www.namespace.com/employee.xsd1"/>
<import namespace="http://www.w3.org/2003/05/soap-encoding"/>
</schmea>
<schmea targerNamespace = "http://www.namespace.com/employee.xsd1"
xmlns:SOAP-ENV = "http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi = "http://www.w3.org/2003/05/XMLSchema-instance"
xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
xmlns:emp = "http://www.namespace.com/employee/employee.xsd1"
<import namespace="http://www.namespace.com/employee.wsdl"/>
<import namespace="http://www.w3.org/2003/05/soap-encoding"/>
<simpleType name="empName">
<restrictions base="xsd:string">
<minLength value="1"/>
<maxLength value="30"/>
</restrictions>
<simpleType name="EmpID">
<restrictions base="xsd:string">
<minLength value="0"/>
<maxLength value="25"/>
</restrictions>
</simpleType>
<complexType name="">
<sequence>
<element name="specialEmployee" type="emp:SpecialEmpDetail minOccurs="0" maxOccurs="1" />
</sequence>
</complexType>
.....
.........
</schema>
</types>
Here is the sample wsdl and java. I can able to generate SpecialEmpDetail.java & EmpDetail.java The ObjectFctory.java should create the mentioned function, but its failed to do so.... Using JAXBElement<> wrapper I can able to generate all functions but the problem here is its a complextType data so wrapping is fine, But String also wrapped this is not expected.
What may be problem?? How can I resolve it??
Thanks in Advance!
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
I have the following in a WSDL file:
<definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns="urn:zimbraAdmin"
xmlns:zns="urn:zimbra"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="urn:zimbraAdmin">
<element name="AuthResponse">
<complexType>
<sequence>
<element name="authToken" type="xsd:string" />
<element name="lifetime" type="xsd:string"/>
<element ref="tns:a" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
<message name="AuthResponse">
<part name="AuthResponse" element="tns:AuthResponse"/>
</message>
<operation name="AuthRequest">
<input message="tns:AuthRequest"/>
<output message="tns:AuthResponse"/>
</operation>
However, when the following request gets sent:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:AuthRequest xmlns:ns2="urn:zimbraAdmin" xmlns:ns3="urn:zimbra">
<name>admin</name>
<password>password</password>
</ns2:AuthRequest>
</S:Body>
</S:Envelope>
The following comes back:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<context xmlns="urn:zimbra">
<change token="2099" />
</context>
</soap:Header>
<soap:Body>
<AuthResponse xmlns="urn:zimbraAdmin">
<authToken>0_c728cf3ae4049ecb8fa5eb19f19397e4661e53a2_69643d33363a38373861353736372d356630632d343266352d623466372d6166666163383064326133643b6578703d31333a313337343533383131303638333b61646d696e3d313a313b747970653d363a7a696d6272613b</authToken>
<lifetime>43199997</lifetime>
<a n="zimbraIsDomainAdminAccount">false</a>
</AuthResponse>
</soap:Body>
</soap:Envelope>
The problem I have is that authToken and lifetime are not assigned (i.e. they come back null)
The code generated for AuthResponse (which was generated with cxf 2.7.5 wsdl2java) looks like follows:
#XmlRootElement(name = "AuthResponse")
public class AuthResponse {
#XmlElement(required = true)
protected String authToken;
#XmlElement(required = true)
protected String lifetime;
#XmlElement(namespace = "urn:zimbraAdmin", required = true)
protected List<A> a;
I believe that if it read as follows my problems would be solved:
#XmlRootElement(name = "AuthResponse")
public class AuthResponse {
#XmlElement(namespace = "urn:zimbraAdmin",required = true)
protected String authToken;
#XmlElement(namespace = "urn:zimbraAdmin",required = true)
protected String lifetime;
#XmlElement(namespace = "urn:zimbraAdmin", required = true)
protected List<A> a;
The question is, what do I need to change in the WSDL file so that the correct code for the client is generated?
EDIT
For reference, I am using the zimbra.wsdl available from http://blog.jeshurun.ca/wp-content/uploads/2011/12/zimbra.wsdl
I have a web-service, defined by writing its WSDL and underlaying XSD, and the java server code classes / java bindings were generated using JAXB/xjc.
Everything looks fine service is running properly... but for every request (looking well-formed after receiving when looking on log-output) the nested elements seem to be always null when accessing through my java code.
Can someone figure out why customerId.getCustomer() always returns null?
My XSD (partly):
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:tip="http://example.org/tip" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://example.org/tip/pro">
<complexType name="id">
<attribute name="id" type="int" use="required"/>
<attribute name="name" type="string" use="optional"/>
</complexType>
<complexType name="customer_id">
<sequence>
<element name="customer" type="tip:id" minOccurs="0"/>
</sequence>
</complexType>
<element name="get_customer_request" type="tip:customer_id"/>
</schema>
The generated class CustomerId:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "customer_id", propOrder = {"customer"})
public class CustomerId {
protected Id customer;
public Id getCustomer() {
return customer;
}
public void setCustomer(Id value) {
this.customer = value;
}
}
The generated class for Id look similar, I don't think there is something special.
In my request handler I got the following extract:
Handler:
JAXBElement<?> request = requestHandler.unmarshallRequest(inputStream);
Object jaxbClass = request.getDeclaredType();
expectedClass = CustomerId.class;
// next line does not throw exception with given XML
if (jaxbClass != expectedClass) throw new IllegalArgumentException();
CustomerId customerId = (CustomerId)request.getValue();
if (customerId == null) {
logInfo("customerId: null");
} else if (customerId.getCustomer() == null) {
// this is the part that always will be executed... why?
logInfo("customerId.customer: null");
} else {
logInfo("customer id: " + customerId.getCustomer().getId());
// return mbean.getCustomer(customerId);
}
And finally an example request XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<m:get_customer_request xmlns:m="http://example.org/tip/pro">
<customer id="0" name="help"/>
</m:get_customer_request>
I stripped out SOAP envelope and body tags, since this is not causing any trouble.
Can anyone see, what I am doing wrong? (I am pretty sure, I do...)
Thanks for your effords!
PART 1
When I create a new Id and set customerId.customer with this, the full
output is
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<get_customer_request xmlns="example.com/tip/pro">
<customer name="xy" id="1"/>
</get_customer_request>
Based on this information it appears that your JAXB mappings expect the customer element to be in the example.com/tip/pro namespace, and your request document should be:
<?xml version="1.0" encoding="ISO-8859-1"?>
<m:get_customer_request xmlns:m="http://example.org/tip/pro">
<m:customer id="0" name="help"/>
</m:get_customer_request>
PART 2
When putting m: prefix to customer element in my request, the parser
complains that he found m:customer and expected customer.
This means that your XML schema does not match your mappings. If you expect the customer element to be in the namespace you can change your XML schema to the following:
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns:tip="http://example.org/tip"
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.org/tip/pro"
elementFormDefault="qualified">
...
</schema>
For more information on JAXB and namespaces see:
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
I am implementing the OGC Web Feature Service and part of that is creating a feature schema that will inherit from the OGC schema. My service marshals the XML fine, but the client is unable to unmarshal the XML. I wrote a tester that illustrates the problem:
...
ObjectFactory wfsfactory = new ObjectFactory();
net.opengis.gml.v_3_1_1.ObjectFactory gmlfactory = new net.opengis.gml.v_3_1_1.ObjectFactory();
com.example.ObjectFactory exampleFactory = new com.example.ObjectFactory();
OgcJaxbManager manager = OgcJaxbManager.getInstance();
FeatureCollectionType featureCollection = wfsfactory
.createFeatureCollectionType();
FeaturePropertyType prop = gmlfactory.createFeaturePropertyType();
prop.setFeature(exampleFactory.createFoo(exampleFactory.createFoo()));
featureCollection.setFeatureMember(Arrays.asList(prop));
//marshal to XML
String xml = manager.marshal(wfsfactory
.createFeatureCollection(featureCollection));
log.info(xml);
//unmarshal back to object
FeatureCollectionType afterMarshal = (FeatureCollectionType) manager
.unmarshal(xml);
JAXBElement<? extends AbstractFeatureType> feature = afterMarshal
.getFeatureMember().get(0).getFeature();
if (feature == null) {
log.info("null");
} else {
log.info("not null");
}
...
Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns4:FeatureCollection xmlns:ns2="http://www.w3.org/1999/xlink" xmlns:ns1="http://www.opengis.net/gml" xmlns:ns4="http://www.opengis.net/wfs" xmlns:ns3="http://www.w3.org/2001/SMIL20/" xmlns:ns9="http://www.opengis.net/wms" xmlns:ns5="http://www.opengis.net/ows/1.1" xmlns:ns6="http://www.opengis.net/ogc" xmlns:ns10="http://example.com" xmlns:ns7="http://www.opengis.net/ows" xmlns:ns11="http://www.w3.org/2001/SMIL20/Language" xmlns:ns8="http://www.opengis.net/wcs/1.1.1">
<ns1:featureMember>
<ns10:foo>
<ns10:bar>0</ns10:bar>
</ns10:foo>
</ns1:featureMember>
</ns4:FeatureCollection>
null
Here is the OGC schema I am extending:
...
<element name="FeatureCollection" type="gml:FeatureCollectionType" substitutionGroup="gml:_Feature"/>
<!-- =========================================================== -->
<complexType name="FeatureCollectionType">
<annotation>
<documentation>Concrete generic feature collection.</documentation>
</annotation>
<complexContent>
<extension base="gml:AbstractFeatureCollectionType"/>
</complexContent>
</complexType>
<!-- =========================================================== -->
<complexType name="AbstractFeatureCollectionType" abstract="true">
<annotation>
<documentation>A feature collection contains zero or more features.</documentation>
</annotation>
<complexContent>
<extension base="gml:AbstractFeatureType">
<sequence>
<element ref="gml:featureMember" minOccurs="0" maxOccurs="unbounded"/>
<element ref="gml:featureMembers" minOccurs="0"/>
</sequence>
</extension>
</complexContent>
</complexType>
<!-- ===== property for feature association ==== -->
<element name="featureMember" type="gml:FeaturePropertyType"/>
<!-- ============================================================== -->
<complexType name="FeaturePropertyType">
<annotation>
<documentation>Container for a feature - follow gml:AssociationType pattern.</documentation>
</annotation>
<sequence minOccurs="0">
<element ref="gml:_Feature"/>
</sequence>
<attributeGroup ref="gml:AssociationAttributeGroup"/>
</complexType>
<!-- ============================================================== -->
<element name="_Feature" type="gml:AbstractFeatureType" abstract="true" substitutionGroup="gml:_GML"/>
<!-- =========================================================== -->
<complexType name="AbstractFeatureType" abstract="true">
<annotation>
<documentation>An abstract feature provides a set of common properties, including id, metaDataProperty, name and description inherited from AbstractGMLType, plus boundedBy. A concrete feature type must derive from this type and specify additional properties in an application schema. A feature must possess an identifying attribute ('id' - 'fid' has been deprecated).</documentation>
</annotation>
<complexContent>
<extension base="gml:AbstractGMLType">
<sequence>
<element ref="gml:boundedBy" minOccurs="0"/>
<element ref="gml:location" minOccurs="0">
<annotation>
<appinfo>deprecated</appinfo>
<documentation>deprecated in GML version 3.1</documentation>
</annotation>
</element>
<!-- additional properties must be specified in an application schema -->
</sequence>
</extension>
</complexContent>
</complexType>
...
Here is my schema:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsd:schema version="1.0" targetNamespace="http://example.com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:example="http://example.com"
xmlns:gml="http://www.opengis.net/gml"
elementFormDefault="qualified">
<xsd:import namespace="http://www.opengis.net/gml"
schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd"/>
<xsd:element name="foo" type="example:foo"
substitutionGroup="gml:_Feature"/>
<xsd:complexType name="foo">
<xsd:complexContent>
<xsd:extension base="gml:AbstractFeatureType">
<xsd:sequence>
<xsd:element name="bar" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
Here is the POJO that xjc produces:
package com.example;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "foo", propOrder = { "bar" })
public class Foo extends AbstractFeatureType {
protected String bar;
...
Any help would be greatly appreciated.
I made this work, with two caveats.
You didn't post the ObjectContext for com.example, so I used a hand-coded ObjectContext. It is critical to include the
substitutionHeadNamespace="http://www.opengis.net/gml" and substitutionHeadName="_Feature"
values in the #XmlElementDecl for the factory method, otherwise I see the same symptoms, i.e. marshalling OK, unmarshalling is empty, but no exceptions.
com.example.ObjectContext looks like this:
package com.example;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
public ObjectFactory() { }
public Foo createFoo() { return new Foo(); }
#XmlElementDecl(namespace="http://example.com",
name="foo",
substitutionHeadNamespace="http://www.opengis.net/gml",
substitutionHeadName="_Feature")
public JAXBElement<Foo> createFoo(Foo foo) {
return new JAXBElement<Foo>(new QName("http://example.com", "foo"), Foo.class, foo);
}
}
com.example.Foo looks like this, including main:
package com.example;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Arrays;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlAccessType;
import net.opengis.gml.v_3_1_1.AbstractFeatureType;
import net.opengis.gml.v_3_1_1.FeaturePropertyType;
import net.opengis.wfs.v_1_1_0.FeatureCollectionType;
import net.opengis.wfs.v_1_1_0.ObjectFactory;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "foo", propOrder = { "bar" })
public class Foo extends AbstractFeatureType {
#XmlElement
protected String bar = "0";
#Override
public Object createNewInstance() {
return new Foo();
}
public static void main(String[] args) throws JAXBException {
ObjectFactory wfsfactory = new ObjectFactory();
net.opengis.gml.v_3_1_1.ObjectFactory gmlfactory = new net.opengis.gml.v_3_1_1.ObjectFactory();
com.example.ObjectFactory exampleFactory = new com.example.ObjectFactory();
FeatureCollectionType featureCollection = wfsfactory
.createFeatureCollectionType();
FeaturePropertyType prop = gmlfactory.createFeaturePropertyType();
prop.setFeature(exampleFactory.createFoo(exampleFactory.createFoo()));
featureCollection.setFeatureMember(Arrays.asList(prop));
//marshal to XML
JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class, net.opengis.gml.v_3_1_1.ObjectFactory.class, com.example.ObjectFactory.class);
StringWriter sw =new StringWriter();
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(wfsfactory.createFeatureCollection(featureCollection), sw);
System.out.println(sw.toString());
//unmarshal back to object
JAXBElement<FeatureCollectionType> afterMarshal = (JAXBElement<FeatureCollectionType>)
ctx.createUnmarshaller().unmarshal(new StringReader(sw.toString()));
JAXBElement<? extends AbstractFeatureType> feature = afterMarshal
.getValue().getFeatureMember().get(0).getFeature();
if (feature == null) {
System.out.println("null");
} else {
System.out.println("not null");
}
}
}
And this is the output I get:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:FeatureCollection xmlns:ns2="http://www.w3.org/1999/xlink" xmlns:ns1="http://www.opengis.net/gml" xmlns:ns4="http://example.com" xmlns:ns3="http://www.opengis.net/wfs" xmlns:ns5="http://www.w3.org/2001/SMIL20/" xmlns:ns6="http://www.opengis.net/ogc" xmlns:ns7="http://www.opengis.net/ows" xmlns:ns8="http://www.w3.org/2001/SMIL20/Language">
<ns1:featureMember>
<ns4:foo>
<ns4:bar>0</ns4:bar>
</ns4:foo>
</ns1:featureMember>
</ns3:FeatureCollection>
not null
Good luck going forward!