FpML Custom binding jaxb - java

I'm required to use FpML in my project and struggling with generating Java class by JAXB:
[ERROR] Element "{http://www.fpml.org/FpML-5/confirmation}tradeId" shows up in more than one properties.
line 1142 of file:/D:/FpML/schema/fpml/5-5/confirmation/fpml-doc-5-5.xsd
fpml-doc-5.5.xsd is imported into the master schema.
I tried to use inline custom binding (I gave up using an external file) as follows:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns="http://www.fpml.org/FpML-5/confirmation" xmlns:fpml-annotation="http://www.fpml.org/annotation" targetNamespace="http://www.fpml.org/FpML-5/confirmation" ecore:documentRoot="FpML" ecore:nsPrefix="conf" ecore:package="org.fpml.confirmation" version="$Revision: 10163 $" elementFormDefault="qualified" attributeFormDefault="unqualified"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:version="1.0">
....
<xsd:element name="issuer" type="IssuerId"></xsd:element>
<xsd:element name="tradeId" type="TradeId">
<xsd:annotation>
<xsd:appinfo>
<jaxb:property name="tradeIdentifierId"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
The same error still occurs.
Directly editing the schema to rename tradeId would solve the issue but I can't do that. I still can define my own inline binding though.
Can you please shed some light?

Use JAXB version 2. I'm using jaxb-xjc 2.1.13 without issues for FPML 5.5 confirmation.

Related

Is this offical Xml schema invalid or is error limitation of Jaxb

uPnP defines a number of Xml schemas including didl-lite.xsd, including this section:
<xsd:sequence>
<xsd:element ref="dc:title"/>
<xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded"/>
<xsd:group ref="upnp:class.group"/>
<xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
When I tried to build Java classes from this using jaxb it complained
Removing the second xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded" line so we have
<xsd:sequence>
<xsd:element ref="dc:title"/>
<xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded"/>
<xsd:group ref="upnp:class.group"/>
</xsd:sequence>
fixed the issue, and seems to make more sense.
But I am not clear is the Xsd actually invalid or is this just a limitation of generating Jaxb classes from Xsd?
I think both semantically and formally the schema provided is valid.
You can, for instance, verify the schema well-formedness with Java or online, for example, in this site.
The issue you are facing could be considered a kind of limitation of JAXB.
The limitation consists in that the generator encounters a value that has been already taken into consideration in the process of generating your classes, and it has a problem, because it will be unable to generate a property and the corresponding related methods and stuff for this second value because the names are already taken.
I will use the xjc tool for code generation but the solution should be portable to the Maven or Gradle plugins too.
If you run the xjc tool like this:
xjc -d out didl-lite-v2.xsd
the error description will give you a possible solution:
[ERROR] Property "AllowedUnderItem" is already defined. Use <jaxb:property> to resolve this conflict
The mentioned term <jaxb:property> has to do with JAXB XML bindings.
JAXB XML bindings allows you to customize the JAXB Java classes generation process in different ways.
The necessary configuration is provided in a XML file with a certain information.
In this specific use case, you can define the following bindings XML file, let's name it binding.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:bindings schemaLocation="didl-lite-v2.xsd">
<jaxb:bindings
node="//xsd:complexType[#name='container.type']/xsd:sequence/xsd:group[#ref='didl-lite:allowed-under-container'][2]">
<jaxb:property name="allowedUnderContainerAfterUpnpClassGroup"/>
</jaxb:bindings>
<jaxb:bindings
node="//xsd:complexType[#name='item.type']/xsd:sequence/xsd:group[#ref='didl-lite:allowed-under-item'][2]">
<jaxb:property name="allowedUnderItemAfterUpnpClassGroup"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
As you can see, we are indicating that the second occurrence of the allowed-under-item group, represented by the XPath expression //xsd:complexType[#name='item.type']/xsd:sequence/xsd:group[#ref='didl-lite:allowed-under-item'][2], should be treated as allowedUnderItemAfterUpnpClassGroup. We need to do something similar with allowed-under-container.
Then, if you run again the xjc tool passing in this XML bindings file, your classes will be generated successfully:
xjc -d out -b binding.xml didl-lite-v2.xsd
This or this other SO questions could be of help as well.

marshall with xjc created nested classes

<ProductInformation Context="GL">
<Assets>
<Asset ID="assetID" UserTypeID="ID">
<Name>name</Name>
<Reference ClassificationID="id"/>
<Values>
<Value AttributeID="ID">Value1</Value>
<Value AttributeID="ID">Value2</Value>
<MultiValue AttributeID="attributeID">
<Value>value3a</Value>
<Value>value3b</Value>
</MultiValue>
</Values>
</Asset>
</Assets>
<Products>....</Products>
</ProductInformation>
I used this xml->xsd and xjc to create classes from it.
Now I want to create my ProductInformation object,and marshall it.
My problem is xjc create 3 classes and a objectfactory, and some nested classes inside ProductInformation. When I look at the avaliable methods I mostly see getters instead of setters.
"Asset" class has no such methods like;
asset.setValues(List<Value> values)
Also I ended up writing funny code like this;
ProductInformation.Assets.Asset.Values.MultiValue multivalue=new ProductInformation.Assets.Asset.Values.MultiValue();
Is this normal with Jaxb?
The answer given by Ian Roberts is the correct one. I am giving this one to provide some additional information for those people interested in not having inner classes.
XML Schema (schema.xsd)
If JAXB classes are generated from the following XML schema, both the resulting Customer and Employee classes will contain a static nested class called Address (because each contains their own definition of an address). This is in fact why static nested classes are used to avoid name conflict problems.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
targetNamespace="http://www.example.org/company"
xmlns="http://www.example.org/company"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:element name="customer">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="street" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="employee">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="road" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
JAXB Binding File (binding.xml)
A bindings file is used to customize the schema to Java generation. You can specify that everything should be a top level class with localScoping="top-level". When you do this you must make sure to resolve any potential name conflicts.
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="company.xsd">
<jaxb:bindings node="//xsd:element[#name='employee']/xsd:complexType/xsd:sequence/xsd:element[#name='address']/xsd:complexType">
<jaxb:class name="EmployeeAddress"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
XJC Call
Below is an example of specifying a bindings file when using the XJC command to generate Java classes from an XML schema.
xjc -b binding.xml schema.xsd
For More Information
http://blog.bdoughan.com/2011/07/jaxb-xjc-and-nested-classes.html
The way JAXB normally handles multi valued properties is to provide just a getter and no setter for the List<Whatever>, which returns a mutable list - you're supposed to call the getter to retrieve an initially-empty list and then create the member objects for this list using new in the normal way and add them directly to the list. You can new a static nested class in exactly the same way as a top-level one.
Single-valued properties (not lists) should have been generated with both getter and setter.
This is actually just a comment to Blaise Doughan's answer but I want to post the xml.
If you work with a more complex xsd and the path in the node attribute is getting too long, you can:
<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="company.xsd">
<jaxb:bindings node="//xsd:element[#name='employee']">
....
<jaxb:bindings node=".//xsd:element[#name='address']/xsd:complexType">
<jaxb:class name="EmployeeAddress"/>
</jaxb:bindings>
....
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>

Error: Failed to parse a schema by xjc in case of xs:choice

I'm want to generate java classes from a schema using jaxb, but I am getting a parsing error from xjc. I have 2 elements wrapped in a choice then one of the element is again repeated just after choice:
<xs:element name="A">
<xs:complexType>
<xs:choice>
<xs:sequence maxOccurs="unbounded">
<xs:element ref="X"/>
<xs:element ref="Y"/>
</xs:sequence>
<xs:element ref="Y"/>
</xs:choice>
</xs:complexType>
</xs:element>
jaxb is throwing:
[ERROR] Element "{*something*}Y" shows up in more than one properties.
line *something* of file:/*something*.xsd
PS: my jaxb version is 2.1.13
Take a look at this post on SO. The solution is to provide a custom binding file that maps your Y outside the choice to use another property name.
I would probably also map the recurring sequence to a class with two properties (X and Y), but that's something else.
I've also tried a test schema (derived from yours, just added dummy complex elements for X and Y) with version 7.1 of the free NetBeans IDE and it worked out without any need for a custom binding file. The JAXB version that I've used is 2.2.4
I've also tried to make it work as Petru described. Rahul hasn't posted his solution so here my bindings file.
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
version="2.1">
<jaxb:bindings schemaLocation="test.xsd" node="//xs:element[#name='A']/xs:complexType/xs:choice[1]">
<jaxb:property name="OutsideY"/>
</jaxb:bindings>
</jaxb:bindings>
XJC output:
$xjc -version
xjc version "JAXB 2.1.10 in JDK 6"
JavaTM Architecture for XML Binding(JAXB) Reference Implementation, (build JAXB 2.1.10 in JDK 6)
$xjc -p com.example.test -d src -extension -b bindings.xml test.xsd
parsing a schema...
compiling a schema...
com\example\test\A.java
com\example\test\ObjectFactory.java
Maybe someone will read this:
org.jvnet.jaxb2_commons . jaxb2-basics is not working on references !
I have really tried many ways to make this plugin work, and you just can't. (It is also mentioned on github page)
#Stanislav Mamontov helped me a lot.
If somebody is curious, this also works for groups:
XSD:
<xsd:group name="OpticalID">
<xsd:sequence>
<xsd:choice>
<xsd:sequence>
<xsd:group ref="MPCID"/>
<xsd:element ref="trkSub" minOccurs="0"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="trkSub"/>
</xsd:sequence>
</xsd:choice>
</xsd:sequence>
BINDING:
<jaxb:bindings node="xsd:group[#name='OpticalID']//xsd:sequence[1]/xsd:choice[1]/xsd:sequence[1]/xsd:element[#ref='trkSub']">
<jaxb:property name="trkSubOrNull"/>
</jaxb:bindings>

JAXB XJC - XPath evaluation results in empty target node?

I've got the following simple XSD document (foo.xsd):
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:foo">
<xsd:element name="Person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Height">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Short"/>
<xsd:enumeration value="Average"/>
<xsd:enumeration value="Tall"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
And I'd like to hint to the XJC JAXB compiler that the "Height" element should use a type safe enum class by using an external bindings file, like so (foo.xjb):
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3c.org/2001/XMLSchema"
jxb:version="2.0">
<jxb:bindings schemaLocation="foo.xsd">
<jxb:bindings node="//xsd:element[#name='Height']/xsd:simpleType">
<jxb:typesafeEnumClass name="Height" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
But when I run the command "xjc -b foo.xjb foo.xsd" I get the following error:
parsing a schema...
[ERROR] XPath evaluation of "//xsd:element[#name='Height']/xsd:simpleType" results in empty target node
line 6 of file:/Users/maerics/src/java/jaxb/foo.xjb
Failed to parse a schema.
The XPath expression looks fine to me so I'm guessing there is some subtle problem related to XML namespaces? I've tried a few combinations of using (or not) a default namespace, targetNamespace, etc. but always the same error. Note that xjc generates Java source for the XSD file by itself, without the external bindings file, as expected. Similarly, using embedded binding definitions in the XSD file works as expected.
Note that I am using Java version "1.6.0_26" and xjc version "JAXB 2.1.10 in JDK 6" on Mac OS 10.6.8.
Can someone explain how to achieve this goal without modifying the original XSD?
Heh, you're going to kick yourself when you see the problem:
In foo.xsd, you have this:
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
In foo.xjb, you have this:
xmlns:xsd="http://www.w3c.org/2001/XMLSchema"
Note "w3" vs. "w3c". Those two attributes need to match exactly, and then your XPath will work (otherwise the namespace referenced in your xjb is distinct from the XSD namespace referenced in your XSD.)

JAXB Generation nillable=true

Using JAXB 2.2.4 I am generating Java code with the following binding file:
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings generateElementProperty="false">
</globalBindings>
Unfortunately, the generated code has a nillable = true annotation. See the following example:
#XmlElement(name = "ArtID", nillable = true)
protected STEBeitrag artID;
This is the definition of STEBeitrag:
<xsd:complexType name="CT_Beitrag">
<xsd:complexContent>
<xsd:extension base="allgemein:CT_Objekt">
<xsd:sequence>
<xsd:element name="ArtID" type="daten:STE_Beitrag" minOccurs="0" maxOccurs="1" nillable="true"/></xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="STE_Beitrag" abstract="true">
<xsd:simpleContent>
<xsd:extension base="xsd:string"/>
</xsd:simpleContent>
</xsd:complexType>
If I do not set the ArtID in the generated CT_Beitrag object then the unmarshaller produces an output like
<ns:ArtID xsi:nil="true"/>
The element ArtID has an abstract type and therefore this XML output is invalid.
How can I generate code with JAXB that omits the nillable=true in the XmlElement annotation?
By the way, the schema canĀ“t be changed.
I have no solution, but this problem is addressed in bug
http://java.net/jira/browse/JAXB-890
I hope this problem wil be solved.
I don't how to do what you're asking and I'd be surprised if what you're asking is worth the effort.
There are 2 options that jump to my mind:
Change the schema (I know you said you can't but perhaps you can take a local copy of the schema if you can't change it due to it being hosted on a server outside of your control)
Change the generated code... simply change nillable=true to nillable=false

Categories