WSDL - allow different order of DataMembers for SOAP messages - servicestack

We use ServiceStack 5.9.2.
DTO:
[DataContract]
[Restrict(Usage.SoapOnly)]
public class GetDocumentations : Documentations
{
}
[DataContract]
[Api("Abfrage auf von geplanten zu dokumentierenden Interventionen")]
public class Documentations
{
[DataMember]
[ApiMember(Description = "Ist dieses Feld gesetzt werden nur die Interventionen abgefragt, die sich seit dem letzten Acknowledge geƤndert haben.")]
public bool? OnlyChanged { get; set; }
[DataMember]
public DocumentationType Type { get; set; }
[DataMember]
public int[] SubTypeIds { get; set; }
[DataMember]
public int[] CustomerIds { get; set; }
[DataMember(IsRequired = true)]
public DateTime From { get; set; }
[DataMember(IsRequired = true)]
public DateTime To { get; set; }
[DataMember]
[ApiMember(Description = "Die Ergebnismenge wird auf x Elemente eingeschraenkt.")]
public int? Limit { get; set; }
}
resulting WSDL snipped:
<xs:complexType name="Documentations">
<xs:sequence>
<xs:element minOccurs="0" name="CustomerIds" nillable="true" xmlns:q28="http://schemas.microsoft.com/2003/10/Serialization/Arrays" type="q28:ArrayOfint" />
<xs:element name="From" type="xs:dateTime" />
<xs:element minOccurs="0" name="Limit" nillable="true" type="xs:int" />
<xs:element minOccurs="0" name="OnlyChanged" nillable="true" type="xs:boolean" />
<xs:element minOccurs="0" name="SubTypeIds" nillable="true" xmlns:q29="http://schemas.microsoft.com/2003/10/Serialization/Arrays" type="q29:ArrayOfint" />
<xs:element name="To" type="xs:dateTime" />
<xs:element minOccurs="0" name="Type" type="tns:DocumentationType" />
</xs:sequence>
</xs:complexType>
enforces that the order in the incoming soap request is like defined:
<?xml version="1.0" encoding="UTF-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap12:Body>
<GetDocumentations xmlns="http://schemas.datacontract.org/2004/07/Company" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<From>2014-01-01T00:00:00</From>
<Limit>100</Limit>
<OnlyChanged>false</OnlyChanged>
<To>2100-01-01T00:00:00</To>
<Type>CarePlan</Type>
</GetDocumentations>
</soap12:Body>
</soap12:Envelope>
That works, but the following not, because the Limit Property is at a different position:
<?xml version="1.0" encoding="UTF-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap12:Body>
<GetDocumentations xmlns="http://schemas.datacontract.org/2004/07/Company" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<From>2014-01-01T00:00:00</From>
<OnlyChanged>false</OnlyChanged>
<To>2100-01-01T00:00:00</To>
<Type>CarePlan</Type>
<Limit>100</Limit>
</GetDocumentations>
</soap12:Body>
</soap12:Envelope>
Here the limit is ignored. Means: It is not mapped to it's property.
Change the xs:sequence to xs:all would fix that. How can we reach that? Or is there a better solution? The problem occures for many DTO's.

You can change the Order in which fields should be serialized & deserialized with the DataMember Order property, but the DataContractSerializer doesn't support accepting them being deserialized in any order.

Related

How to change XmlType of generated JAXB classes

I am using gradle to generate Java classes based on an XML Schema file. I am using 'org.glassfish.jaxb:jaxb-xjc:2.2.11' and 'org.glassfish.jaxb:jaxb-runtime:2.2.11' as dependencies so I can use the 'com.sun.tools.xjc.XJC2Task' class to generate the classes.
This is the schema file:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="test"
targetNamespace="urn:oio:records:1.0.0"
xmlns="urn:oio:records:1.0.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="records" type="recordsType"/>
<xs:element name="record" type="recordType"/>
<xs:complexType name="recordsType">
<xs:sequence>
<xs:element ref="record" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="recordType">
<xs:attribute name="key" type="xs:string"/>
<xs:attribute name="value" type="xs:string"/>
</xs:complexType>
</xs:schema>
One of the generated classes look like this:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "recordType")
public class RecordType {
#XmlAttribute(name = "key")
protected String key;
#XmlAttribute(name = "value")
protected String value;
public String getKey() {return key;}
public void setKey(String value) {this.key = value;}
public String getValue() {return value;}
public void setValue(String value) {this.value = value;}
}
How can I change the name value in the #XmlType annotation? I would like it to be
#XmlType(name = "record")
I have tried using a bindingsfile and tried to experiment with the <javaType> tag in the bindingsfile, but without luck.
EDIT:
The reason I need to change this is that I need to split an XML file using the stax splitter from Camel (http://camel.apache.org/stax.html section called "Iterate over a collection using JAXB and StAX").
This looks at the name attribute of the #XmlType annotation to recognize the xml tag to split on in the file. The recognized tag (<record>) will then be JAXB parsed to a RecordType java class.
The name in the #XmlType annotation is the name of the complexType in your schema file. This is how the parameter 'name' is defined for this annotation.
So, if you want to change it, you have to change the name of the complexType in your schema:
<xs:complexType name="record">
<xs:attribute name="key" type="xs:string"/>
<xs:attribute name="value" type="xs:string"/>
</xs:complexType>
You can use the jaxb2-annotate-plugin to override the value of the name attribute in the generated Java class.
For your code, it would look like this:
<xs:schema id="test"
targetNamespace="urn:oio:records:1.0.0"
xmlns="urn:oio:records:1.0.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="annox"
elementFormDefault="qualified">
<xs:element name="records" type="recordsType"/>
<xs:element name="record" type="recordType"/>
<xs:complexType name="recordsType">
<xs:sequence>
<xs:element ref="record" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="recordType">
<xs:annotation>
<xs:appinfo>
<annox:annotate target="class">
#javax.xml.bind.annotation.XmlType(name = "record")
</annox:annotate>
</xs:appinfo>
</xs:annotation>
<xs:attribute name="key" type="xs:string"/>
<xs:attribute name="value" type="xs:string"/>
</xs:complexType>
</xs:schema>
I don't know if this should be considered a hack, but it does the trick. Interestingly enough, in my case even the namespace attribute of XmlType is still generated and filled with the same value as without adding that explicit annotation.

JAXB schema to Java Different XmlRootElement name and Class name

I have a xsd schema from which I'm generating some java classes. I'm using jaxb for the generation.
I want to be able to generate a class annotated with #XmlRootElement, but I want the #XmlRootElement name property to be different than the name of the generated class.
In my xsd I'm defining the following:
<xs:element name="customer">
<xs:complexType>
<xs:sequence>
....
</xs:sequence>
</xs:complexType>
</xs:element>
This piece of code generates the following java class:
#XmlRootElement(name = "customer")
public class Customer {
...
}
The name property of the #XmlRootElement is the same as the name of the generated Class. I want the generated class name to be CustomerRequest.
I've tryed to use the jaxb:class definition to change the classe name. Indeed this option changes the class name but removes the #XmlRootElement annotation, and I need it to be present.
The following xsd:
<xs:element name="customer">
<xs:complexType>
<xs:annotation>
<xs:appinfo>
<jaxb:class name="CustomerRequest"/>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
Generates this class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "customer", propOrder = {
})
public class CustomerRequest {
}
How can I make the property name of the #XmlRootElement annotation different from the generated class name without loosing the annotation?
Solution update:
User Xstian proposed the correct solution using external bindings.
Just for further reference, I'll update my own post with the solution converted for using inline bindings:
<xs:element name="customer">
<xs:complexType>
<xs:annotation>
<xs:documentation>Request object for the operation that checks if a customer profile exists.</xs:documentation>
<xs:appinfo>
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="customer"/>
</annox:annotate>
<jaxb:class name="CustomerRequest"/>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
</xs:sequece>
</xs:complexType>
</xs:element>
I suggest you to use this bindings
<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:annox="http://annox.dev.java.net"
xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix">
<bindings schemaLocation="../your.xsd">
<bindings node="//xs:element[#name='customer']//xs:complexType">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement"
name="customer" namespace="yourNamespaceIfYouWant">
</annox:annotate>
</annox:annotate>
<class name="CustomerRequest"/>
</bindings>
</bindings>
</bindings>
Class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"header"
})
#XmlRootElement(name = "customer", namespace = "yourNamespaceIfYouWant")
public class CustomerRequest

error trying to marshal a JAXB root object missing #XmlRootElement

I have a complex xml schema that is part of an international standard, therefore I can't change the schema files, and I have used Maven to generate JAXB objects from them. When I try to set data into my JAXB objects and then marshal the root element I get the missing #XmlRootElement error on several of the complex types. My question is how do I resolve this?
Environment:
JAXB 2.2.2
Maven 3.0.3
Eclipse Juno
Java 1.6
Windows 7 64 bit
I have researched the web and this site extensively but have not found an answer to my problem, including this post:
http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html
and this question on stack overflow:
JAX-WS MarshalException with custom JAX-B bindings: Unable to marshal type "java.lang.String" as an element because it is missing an #XmlRootElement annotation
I have tried adding an annotation to the offending classes in my custom binding file, but it adds the annotation to the class as well as the getContent() method and the class won't compile. I don't think I should have to add this annotation anyway, since this is a complex type that is a component of the root, actually it's nested fairly deep in the tree. I have read that you can add the <xjc:simple/> tag to the global binding element, but I have added a number of attributes to the global binding element and it won't compile when I do that.
Can someone help point me in the right direction here, could this be an error in the way I am building up the JAXB objects? I have walked it through in the debugger and it seems that when the ArrayReferenceNodeProperty class from the package com.sun.xml.bind.v2.runtime.property tries to serialize the list body and when it gets the JaxBeanInfo for these classes there isn't a dom handler set and the jaxbType is not an object so it thinks it needs to be a root.
I am not using this in a web based service and other than the tweaks in the binding file to resolve naming conflicts have not created any custom classes or bindings.
Here is the top level schema file:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:annotation>
<xs:documentation>
*****************************************************************************
* *
* S1000D Issue 3 *
* XML Schema *
* *
* Release Version 3.0 *
* Date: 2007-07-31 *
* *
* *
* The following attribute definition on the root element may be used to *
* call this set of declarations:- *
* *
* xsi:noNamespaceSchemaLocation= *
* "http://www.s1000d.org/S1000D_3-0/xml_schema_master/dm/procedSchema.xsd" *
*****************************************************************************
</xs:documentation>
</xs:annotation>
<xs:redefine schemaLocation="elementGroups.xsd">
<xs:group name="APPLIC">
<xs:choice>
<xs:sequence>
<xs:element ref="displaytext"/>
<xs:choice minOccurs="0">
<xs:element ref="assert"/>
<xs:element ref="evaluate"/>
</xs:choice>
</xs:sequence>
<xs:choice>
<xs:element ref="assert"/>
<xs:element ref="evaluate"/>
</xs:choice>
</xs:choice>
</xs:group>
<xs:group name="NPAR">
<xs:sequence>
<xs:group ref="WC"/>
<xs:group ref="NPFFT" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:group>
<xs:group name="NPFFT">
<xs:choice>
<xs:group ref="NP"/>
<xs:group ref="FFT"/>
</xs:choice>
</xs:group>
<xs:group name="paracon">
<xs:choice>
<xs:group ref="text"/>
<xs:group ref="list"/>
</xs:choice>
</xs:group>
<xs:group name="text">
<xs:choice>
<xs:element ref="ein"/>
<xs:element ref="cb"/>
<xs:element ref="parasigdata"/>
<xs:element ref="quantity"/>
<xs:element ref="xref"/>
<xs:element ref="indxflag"/>
<xs:element ref="change"/>
<xs:element ref="emphasis"/>
<xs:element ref="symbol"/>
<xs:element ref="subscrpt"/>
<xs:element ref="supscrpt"/>
<xs:element ref="refdm"/>
<xs:element ref="reftp"/>
<xs:element ref="ftnote"/>
<xs:element ref="ftnref"/>
<xs:element ref="acronym"/>
<xs:element ref="acroterm"/>
<xs:element ref="capgrp"/>
</xs:choice>
</xs:group>
<xs:group name="TEXT-NOREFS">
<xs:choice>
<xs:element ref="xref"/>
<xs:element ref="indxflag"/>
<xs:element ref="symbol"/>
<xs:element ref="subscrpt"/>
<xs:element ref="supscrpt"/>
<xs:element ref="ftnref"/>
<xs:element ref="acronym"/>
<xs:element ref="acroterm"/>
</xs:choice>
</xs:group>
<xs:group name="STEP1">
<xs:sequence>
<xs:element ref="step1"/>
</xs:sequence>
</xs:group>
<xs:group name="STEP2">
<xs:sequence>
<xs:element ref="step2"/>
</xs:sequence>
</xs:group>
<xs:group name="STEP3">
<xs:sequence>
<xs:element ref="step3"/>
</xs:sequence>
</xs:group>
<xs:group name="STEP4">
<xs:sequence>
<xs:element ref="step4"/>
</xs:sequence>
</xs:group>
<xs:group name="STEP5">
<xs:sequence>
<xs:element ref="step5"/>
</xs:sequence>
</xs:group>
<xs:group name="STEP6">
<xs:sequence>
<xs:element ref="step6"/>
</xs:sequence>
</xs:group>
<xs:group name="STEP7">
<xs:sequence>
<xs:element ref="step7"/>
</xs:sequence>
</xs:group>
<xs:group name="STEP8">
<xs:sequence>
<xs:element ref="step8"/>
</xs:sequence>
</xs:group>
</xs:redefine>
<xs:redefine schemaLocation="complexTypes.xsd">
<xs:complexType name="contentType">
<xs:complexContent>
<xs:restriction base="contentType">
<xs:sequence>
<xs:element ref="refs" minOccurs="0"/>
<xs:element ref="proced"/>
</xs:sequence>
<xs:attribute ref="id"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
<xs:element name="dmodule" type="dmoduleType"/>
For the xrefType I am only setting two attributes and for the refdmType I am only setting one other complex type that is part of the ALLDMC group. The code for the two complex types that error is:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:import namespace="http://www.w3.org/1999/02/22-rdf-syntax-ns#" schemaLocation="rdf.xsd"/>
<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd"/>
<xs:include schemaLocation="attributeGroups.xsd"/>
<xs:include schemaLocation="simpleElements.xsd"/>
<xs:include schemaLocation="complexElements.xsd"/>
<xs:include schemaLocation="elementGroups.xsd"/>
<xs:complexType name="refdmType">
<xs:choice>
<xs:sequence>
<xs:element ref="applic" minOccurs="0"/>
<xs:element ref="dmcextension" minOccurs="0"/>
<xs:group ref="ALLDMC"/>
<xs:element ref="issno" minOccurs="0"/>
<xs:element ref="dmtitle" minOccurs="0"/>
<xs:element ref="language" minOccurs="0"/>
</xs:sequence>
<xs:group ref="xlink:XLINKEXT" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute ref="target"/>
<xs:attribute ref="refapplic"/>
<xs:attributeGroup ref="bodyatt"/>
<xs:attributeGroup ref="cntlcontent"/>
<xs:attributeGroup ref="xlink:XLINKATT"/>
</xs:complexType>
<xs:complexType name="xrefType" mixed="true">
<xs:sequence>
<xs:element ref="applic" minOccurs="0"/>
<xs:group ref="SPARCON" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="xrefid"/>
<xs:attribute ref="xidtype"/>
<xs:attribute ref="target"/>
<xs:attribute ref="destitle"/>
<xs:attribute ref="pretext"/>
<xs:attribute ref="posttext"/>
<xs:attribute ref="refapplic"/>
<xs:attributeGroup ref="cntlcontent"/>
<xs:attributeGroup ref="xlink:XLINKATT3"/>
</xs:complexType>
</xs:schema>
And here is the main part of the JAXB generated classes. I have removed most of the getters and setters to save space:
The RefdmType:
/**
* <p>Java class for refdmType complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="refdmType">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <choice>
* <sequence>
* <element ref="{}applic" minOccurs="0"/>
* <element ref="{}dmcextension" minOccurs="0"/>
* <group ref="{}ALLDMC"/>
* <element ref="{}issno" minOccurs="0"/>
* <element ref="{}dmtitle" minOccurs="0"/>
* <element ref="{}language" minOccurs="0"/>
* </sequence>
* <group ref="{http://www.w3.org/1999/xlink}XLINKEXT" maxOccurs="unbounded" minOccurs="0"/>
* </choice>
* <attGroup ref="{http://www.w3.org/1999/xlink}XLINKATT"/>
* <attGroup ref="{}cntlcontent"/>
* <attGroup ref="{}bodyatt"/>
* <attribute ref="{}target"/>
* <attribute ref="{}refapplic"/>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "refdmType", propOrder = {
"applicAndDmcextensionAndAge"
})
public class RefdmType implements Serializable
{
private final static long serialVersionUID = 1L;
#XmlElements({
#XmlElement(name = "applic", type = ApplicType.class),
#XmlElement(name = "dmcextension", type = DmcextensionType.class),
#XmlElement(name = "age", type = AgeType.class),
#XmlElement(name = "avee", type = AveeType.class),
#XmlElement(name = "issno", type = IssnoType.class),
#XmlElement(name = "dmtitle", type = DmtitleType.class),
#XmlElement(name = "language", type = LanguageType.class),
#XmlElement(name = "resource", namespace = "http://www.w3.org/1999/xlink", type = Resource.class),
#XmlElement(name = "locator", namespace = "http://www.w3.org/1999/xlink", type = Locator.class),
#XmlElement(name = "arc", namespace = "http://www.w3.org/1999/xlink", type = Arc.class)
})
protected List<Serializable> applicAndDmcextensionAndAge;
#XmlAttribute(name = "target")
protected String target;
#XmlAttribute(name = "refapplic")
#XmlIDREF
#XmlSchemaType(name = "IDREF")
protected Object refapplic;
#XmlAttribute(name = "type", namespace = "http://www.w3.org/1999/xlink")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String type;
#XmlAttribute(name = "href", namespace = "http://www.w3.org/1999/xlink")
protected String href;
#XmlAttribute(name = "title", namespace = "http://www.w3.org/1999/xlink")
protected String title;
#XmlAttribute(name = "show", namespace = "http://www.w3.org/1999/xlink")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String show;
#XmlAttribute(name = "actuate", namespace = "http://www.w3.org/1999/xlink")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String actuate;
#XmlAttribute(name = "authname")
protected String authname;
#XmlAttribute(name = "authdoc")
protected String authdoc;
#XmlAttribute(name = "id")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlID
#XmlSchemaType(name = "ID")
protected String id;
#XmlAttribute(name = "level")
#XmlSchemaType(name = "nonNegativeInteger")
protected BigInteger level;
#XmlAttribute(name = "mark")
#XmlSchemaType(name = "nonNegativeInteger")
protected BigInteger mark;
#XmlAttribute(name = "change")
protected ChangeType change;
#XmlAttribute(name = "rfc")
protected String rfc;
/**
* Gets the value of the applicAndDmcextensionAndAge 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 applicAndDmcextensionAndAge property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getApplicAndDmcextensionAndAge().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link ApplicType }
* {#link DmcextensionType }
* {#link AgeType }
* {#link AveeType }
* {#link IssnoType }
* {#link DmtitleType }
* {#link LanguageType }
* {#link Resource }
* {#link Locator }
* {#link Arc }
*
*
*/
public List<Serializable> getApplicAndDmcextensionAndAge() {
if (applicAndDmcextensionAndAge == null) {
applicAndDmcextensionAndAge = new ArrayList<Serializable>();
}
return this.applicAndDmcextensionAndAge;
}
}
The XrefType:
/**
* <p>Java class for xrefType complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="xrefType">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element ref="{}applic" minOccurs="0"/>
* <group ref="{}SPARCON" maxOccurs="unbounded" minOccurs="0"/>
* </sequence>
* <attGroup ref="{}cntlcontent"/>
* <attGroup ref="{http://www.w3.org/1999/xlink}XLINKATT3"/>
* <attribute ref="{}xrefid"/>
* <attribute ref="{}xidtype"/>
* <attribute ref="{}target"/>
* <attribute ref="{}destitle"/>
* <attribute ref="{}pretext"/>
* <attribute ref="{}posttext"/>
* <attribute ref="{}refapplic"/>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "xrefType", propOrder = {
"content"
})
public class XrefType implements Serializable
{
private final static long serialVersionUID = 1L;
#XmlElementRefs({
#XmlElementRef(name = "supscrpt", type = JAXBElement.class),
#XmlElementRef(name = "subscrpt", type = JAXBElement.class),
#XmlElementRef(name = "applic", type = JAXBElement.class)
})
#XmlMixed
protected List<Serializable> content;
#XmlAttribute(name = "xrefid")
#XmlJavaTypeAdapter(Adapter5 .class)
#XmlSchemaType(name = "IDREF")
protected String xrefid;
#XmlAttribute(name = "xidtype")
protected XidtypeType xidtype;
#XmlAttribute(name = "target")
protected String target;
#XmlAttribute(name = "destitle")
protected String destitle;
#XmlAttribute(name = "pretext")
protected String pretext;
#XmlAttribute(name = "posttext")
protected String posttext;
#XmlAttribute(name = "refapplic")
#XmlIDREF
#XmlSchemaType(name = "IDREF")
protected Object refapplic;
#XmlAttribute(name = "authname")
protected String authname;
#XmlAttribute(name = "authdoc")
protected String authdoc;
#XmlAttribute(name = "type", namespace = "http://www.w3.org/1999/xlink")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String type;
#XmlAttribute(name = "href", namespace = "http://www.w3.org/1999/xlink")
protected String href;
#XmlAttribute(name = "title", namespace = "http://www.w3.org/1999/xlink")
protected String title;
#XmlAttribute(name = "show", namespace = "http://www.w3.org/1999/xlink")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String show;
#XmlAttribute(name = "actuate", namespace = "http://www.w3.org/1999/xlink")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String actuate;
/**
* 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 String }
* {#link JAXBElement }{#code <}{#link String }{#code >}
* {#link JAXBElement }{#code <}{#link ApplicType }{#code >}
* {#link JAXBElement }{#code <}{#link String }{#code >}
*
*
*/
public List<Serializable> getContent() {
if (content == null) {
content = new ArrayList<Serializable>();
}
return this.content;
}
}
And finally here is my custom binding file:
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:annox="http://annox.dev.java.net"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd">
<jxb:globalBindings typesafeEnumMemberName="generateName"
typesafeEnumMaxMembers="1500" collectionType="java.util.ArrayList"
generateValueClass="true" choiceContentProperty="true">
<xjc:serializable uid="1" />
</jxb:globalBindings>
<jxb:bindings schemaLocation="simpleTypes.xsd" node="/xs:schema">
<jxb:bindings node="//xs:simpleType[#name='YEAR']">
<jxb:javaType name="java.lang.Integer" />
</jxb:bindings>
<jxb:bindings node="//xs:simpleType[#name='DAY']">
<jxb:javaType name="java.lang.String" />
</jxb:bindings>
<jxb:bindings node="//xs:simpleType[#name='MONTH']">
<jxb:javaType name="java.lang.String" />
</jxb:bindings>
<jxb:bindings node="//xs:simpleType[#name='issnovalueType']">
<jxb:javaType name="java.lang.String" />
</jxb:bindings>
</jxb:bindings>
<jxb:bindings schemaLocation="attributes.xsd" node="/xs:schema">
<jxb:bindings node="xs:attribute[#name='inwork']">
<jxb:property>
<jxb:baseType>
<jxb:javaType name="java.lang.String" />
</jxb:baseType>
</jxb:property>
</jxb:bindings>
<jxb:bindings node="//xs:attribute[#name='xrefid']">
<jxb:property>
<jxb:baseType>
<jxb:javaType name="java.lang.String" />
</jxb:baseType>
</jxb:property>
</jxb:bindings>
</jxb:bindings>
<jxb:bindings schemaLocation="complexTypes.xsd" node="/xs:schema">
<jxb:bindings node="xs:complexType[#name='dmoduleType']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement"
name="dmodule" />
</annox:annotate>
</jxb:bindings>
<jxb:bindings node="//xs:complexType[#name='skillType']">
<jxb:class name="SkillTypeComplex" />
</jxb:bindings>
<!--<jxb:bindings node="//xs:complexType[#name='xrefType']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement"
name="xref" />
</annox:annotate>
<jxb:bindings node=".//xs:sequence//xs:element[#ref='applic']">
<jxb:property name="xrefApplic"/>
</jxb:bindings>
</jxb:bindings>-->
</jxb:bindings>
<jxb:bindings schemaLocation="elementGroups.xsd" node="//xs:group[#name='APPLIC']">
<jxb:bindings node=".//xs:choice//xs:sequence">
<jxb:bindings node=".//xs:choice">
<jxb:property name="assertEvalChoice" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
<jxb:bindings schemaLocation="dc.xsd" node="/xs:schema">
<jxb:bindings node="//xs:element[#name='language']">
<jxb:class name="DcLanguage" />
</jxb:bindings>
<jxb:bindings node="//xs:element[#name='subject']">
<jxb:class name="DcSubject" />
</jxb:bindings>
<jxb:bindings node="//xs:element[#name='title']">
<jxb:class name="DcTitle" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
A high level view of why this would occur and suggestions on how to fix it would be appreciated. I've only been using JAXB for a couple months and am not an expert. Thank you.
Here is the error I'm seeing:
javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: unable to marshal type "com.synesis7.s7exporter.domain.s1000d.dm.common.XrefType" as an element because it is missing an #XmlRootElement annotation]
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:249)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:96)
at com.synesis7.s7exporter.client.s1000d.procedural.S7ProceduralRunnable.writeToXml(S7ProceduralRunnable.java:142)
at com.synesis7.s7exporter.client.s1000d.procedural.S7ProceduralRunnable.createProceduralDm(S7ProceduralRunnable.java:118)
at com.synesis7.s7exporter.client.s1000d.procedural.S7ProceduralRunnable.run(S7ProceduralRunnable.java:93)
at com.synesis7.s7exporter.S7ExporterController.processProceduralDms(S7ExporterController.java:235)
at com.synesis7.s7exporter.S7ExporterController.exportSchema(S7ExporterController.java:118)
at com.synesis7.s7exporter.S7exporter.initializeExporter(S7exporter.java:58)
at com.synesis7.s7exporter.S7exporter.main(S7exporter.java:38)
Caused by: com.sun.istack.SAXException2: unable to marshal type "com.synesis7.s7exporter.domain.s1000d.dm.common.XrefType" as an element because it is missing an #XmlRootElement annotation
at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:252)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:324)
at com.sun.xml.bind.v2.runtime.property.ArrayReferenceNodeProperty.serializeListBody(ArrayReferenceNodeProperty.java:118)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:156)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:156)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:338)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:156)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:156)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:161)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:193)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:321)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:328)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:76)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:498)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:320)
... 9 more
You can wrap your object in an instance of JAXBElement to provide the root element information. If you generated your model from an XML schema there are convenience methods for this on the generated ObjectFactory class.
For More Information
http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html
You can use the ObjectFactory class to workaround for the classes which doesn't have the #XmlRootElement. ObjectFactory has overloaded methods to wrap it around the JAXBElement. Method:1 does the simple creation of the object and Method:2 will wrap the object with #JAXBElement. Always to use Method:2 to avoid javax.xml.bind.MarshalException - with linked exception missing an #XmlRootElement annotation
Method:1
public GetCountry createGetCountry() {
return new GetCountry();
}
Method:2
#XmlElementDecl(namespace = "my/name/space", name = "getCountry")
public JAXBElement<GetCountry> createGetCountry(GetCountry value) {
return new JAXBElement<GetCountry>(_GetCountry_QNAME, GetCountry.class, null, value);
}
hope this is will helpful...

XSD byte[][] issue on Web Service

I'm trying to pass to my web service something like an array of byte array (byte[][]) to do that i created this xsd file:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="FileResponse"
targetNamespace="http://tempuri.org/FileResponse.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/FileResponse.xsd"
xmlns:mstns="http://tempuri.org/FileResponse.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="FileResponse">
<xs:sequence>
<xs:element name="SPResultItem" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="file" type="xs:unsignedByte" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Message" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="FileResponse" type="FileResponse"/>
</xs:schema>
XSD tool generates this:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/FileResponse.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/FileResponse.xsd", IsNullable=false)]
public partial class FileResponse {
private FileResponseSPResultStatus sPResultStatusField;
private sbyte[][] sPResultItemField;
private string messageField;
/// <remarks/>
public FileResponseSPResultStatus SPResultStatus {
get {
return this.sPResultStatusField;
}
set {
this.sPResultStatusField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("file", typeof(sbyte), IsNullable=false)]
public sbyte[][] SPResultItem {
get {
return this.sPResultItemField;
}
set {
this.sPResultItemField = value;
}
}
/// <remarks/>
public string Message {
get {
return this.messageField;
}
set {
this.messageField = value;
}
}
}
As you can see, the conversion seems good: the xsd contains a "sbyte[][]" field... But when i call a method from this webservice (even if it doesn't use this class) it crashes without giving infos...
How can i create an XSD that receives a sbyte[][] or byte[][] and works? Thank you very much!!
I solved this way:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="FileResponse"
targetNamespace="http://tempuri.org/FileResponse.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/FileResponse.xsd"
xmlns:mstns="http://tempuri.org/FileResponse.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="FileResponse">
<xs:sequence>
<xs:element name="SPResultItem" type="fileList" maxOccurs="unbounded"> </xs:element>
<xs:element name="Message" type="xs:string"></xs:element>
</xs:sequence>
<xs:complexType name ="fileList">
<xs:sequence>
<xs:element name="file" type="xs:base64Binary" ></xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="FileResponse" type="FileResponse"/>

Jaxb - Namespace problems with SchemaGen and java.util.Map

When a class contains a java.util.Map, SchemaGen generates an xsd with a namespace on the Map elements. However when the marshaller generates xml from the same class no namespace is present.
This may be solvable with XmlAdapter however that seems to require the creation of 3 extra classes per Map. As I have a large number of maps I don't want to go down this route.
Is there any way to get SchemaGen and the Marshaller to generate the same xml?
Example Classes and schemas:
Test1:
#XmlRootElement
public class Test1 implements Serializable {
private String field1;
private Map<String, Test2> attributes;
public Test1() {}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public Map<String, Test2> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, Test2> attributes) {
this.attributes = attributes;
}
}
Test2:
public class Test2 implements Serializable {
private String name;
private String value;
public Test2() {
}
public Test2(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
SchemaGen output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://testns" xmlns:tns="http://testns" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="test1" type="tns:test1"/>
<xs:complexType name="test1">
<xs:sequence>
<xs:element name="attributes">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="key" minOccurs="0" type="xs:string"/>
<xs:element name="value" minOccurs="0" type="tns:test2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="field1" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="test2">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0"/>
<xs:element name="value" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Xml that conforms to the schema. (note. jaxb will not unmarshall this xml!)
<?xml version="1.0" encoding="UTF-8"?>
<ns1:test1
xmlns:ns1="http://testns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://testns ../build/schemas/schema1.xsd"
>
<ns1:attributes>
<ns1:entry>
<ns1:key>a1</ns1:key>
<ns1:value>
<ns1:name>a1</ns1:name>
<ns1:value>v1</ns1:value>
</ns1:value>
</ns1:entry>
</ns1:attributes>
<ns1:field1>f1</ns1:field1>
</ns1:test1>
Xml that Jaxb produces. (note. It does not conform to the schema!)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:test1 xmlns:ns2="http://testns">
<ns2:attributes>
<entry>
<key>a1</key>
<value>
<ns2:name>a1</ns2:name>
<ns2:value>v1</ns2:value>
</value>
</entry>
</ns2:attributes>
<ns2:field1>f1</ns2:field1>
</ns2:test1>

Resources