JAXB/XJC external binding for renaming versus multiple XSD compile - java

(I've already googled it and done a search here and found no answer, maybe I'm using the wrong keywords...)
To make it simple, I have two schemas:
a.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://foo.bar/something"
targetNamespace="http://foo.bar/something"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="TFoo">
<xs:attribute name="version" type="xs:string" />
</xs:complexType>
</xs:schema>
b.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://foo.bar/something"
targetNamespace="http://foo.bar/something"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="TFoo">
<xs:attribute name="version" type="xs:string" />
<xs:attribute name="dateTime" type="xs:dateTime" />
</xs:complexType>
</xs:schema>
Both have the same targetNamespace and a complexType named TFoo.
I have an external binding to change the generated class name of a.xsd from TFoo to TFooA:
a-binding.xml:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
version="2.1">
<jxb:bindings schemaLocation="a.xsd">
<jxb:bindings node="//xs:complexType[#name='TFoo']">
<jxb:class name="TFooA"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
which works if I compile the a.xsd alone:
$ xjc -b a-binding.xml a.xsd
parsing a schema...
compiling a schema...
bar/foo/something/ObjectFactory.java
bar/foo/something/TFooA.java
bar/foo/something/package-info.java
(look how I got TFooA.java)
But, if I try to compile both schemas at once, I get:
$ xjc -b a-binding.xml a.xsd b.xsd
parsing a schema...
[ERROR] 'TFoo' is already defined
line 13 of file:/home/scherrer/tmp/PL_008f/b.xsd
[ERROR] (related to above error) the first definition appears here
line 9 of file:/home/scherrer/tmp/PL_008f/a.xsd
Failed to parse a schema.
I know TFoo is defined twice, and that's why I have the external binding to solve the conflict.
Obs. both schemas are fictitious, written to exemplify the problem, the real ones (many) are provided by a third party and I can't change them.
Can anyone tell me if this is some kind of xjc restriction (it's not listed here) or shouldn't work at all? Or maybe a bug?
Thanks in advance.

Having 2 different schema documents defining the same name space (and even worse - same element) is equivalent to having 2 different jars contain the same package and same class(es) in the package. This isn't a limitation of jaxb per se - it is a violation of what schema name spaces mean.
In short, you cannot process these schemas together.
The generator cannot create classes because it does not know what to reference. The failure occurs before your attempt to rename. It occurs when reading the schemas.
What you could do is process the schemas separately and change the java package names which are used. This avoids naming conflict in the java package space and basically treats the schema docs as completely separate entities with no references to each other. This can be done by defining the package name to use in the binding:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
version="2.1">
<jxb:bindings schemaLocation="a.xsd" node="/xs:schema">
<jxb:schemaBindings>
<jxb:package name="com.foo.a"></jxb:package>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>

I think you found a limitation of data binding. Try data projection instead (Disclosure: I'm affiliated with that project).
Your schema b.xsd looks just like an extension to the a.xsd. You can create a projection interface suitable for b.xsd and use it with any documents that fit either a.xsd or b.xsd.

Related

XSD to Java objects using the XJC (JAXB) results in [ERROR] Property "Value" is already defined. Use <jaxb:property> to resolve this conflict

There are a lot of answers related to this but for some reason, I am still confused and unable to get the Java objects for my XSD.
I am trying to create the Java objects from XSD using the XJC JAXB but when I run the XJC command it results in the error
[ERROR] Property "Value" is already defined. Use <jaxb:property> to resolve this conflict.
Hence, based on my research I found that I need to write the binding file so I wrote the binding file but still I am getting the same error which means that I am messing up something in the binding file. As I am unable to make it work even after a lot of try I thought of posting it and getting some solution.
Following is my XSD which is failing as per the XJC command failure message foo.xsd:
<xsd:complexType name="DocumentExtensionType">
<xsd:sequence>
<xsd:any namespace="##local" processContents="lax" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:anyAttribute processContents="lax"/>
</xsd:complexType>
Following are the JAXB bindings I tried and executed but still results in an error: foo.xjb
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:bindings schemaLocation="foo.xsd">
<jxb:bindings
node="//xsd:complexType[#name='DocumentExtensionType']/xsd:sequence/xsd:choice/xsd:any[#namespace='http://checklists.nist.gov/sccf/0.1']">
<jxb:property name="any2" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Following is another JAXB binding I've tried: foo.xjb
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
version="2.1">
<bindings schemaLocation="foo.xsd" version="1.0">
<schemaBindings>
<package name="com.track.doc"/>
</schemaBindings>
<bindings node="//xsd:complexType[#name='DocumentExtensionType']/xsd:sequence/xsd:any[#namespace='']">
<property name="any2"/>
</bindings>
</bindings>
</bindings>
Following is the command I am running in my terminal:
xjc -p "com.track.doc" -d "/Users/batman/Downloads/XSD" -b foo.xjb foo.xsd
Can someone please guide me what am I doing mistake?
After trying a lot of things finally this code worked for me. However, I posted only a chunk of XSD which was failing when I run this for this small chunk then it works but when I run for the whole XSD it still fails. Not completely sure what's going wrong.
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
version="2.1">
<bindings schemaLocation="foo.xsd" version="1.0">
<schemaBindings>
<package name="com.track.doc"/>
</schemaBindings>
<bindings node="//xsd:complexType[#name='DocumentExtensionType']/xsd:sequence">
<property name="seq1"/>
</bindings>
</bindings>
</bindings>
One more issue that I noticed in my XSD. If incase you are also having the similar issue then following might help:
Make sure that your XSD file which you are passing as input does not have any field with the name as value.
In my case I had a field with name = "value".
<xsd:attribute type="xsd:float" name="value" use="optional"/>
I replaced it with
<xsd:attribute type="xsd:float" name="floatValue" use="optional"/>

JAXB Duplicate class renaming

Hi I wonder if anyone can help me. I have got two .xsd schema files orderservice-order.xsd and order.xsd each of which name an element type of "order".
order.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xml.xxxxxxxx.com/order"
<xs:element name="order">
<xs:complexType>
<xs:sequence>
<xs:element name="client" type="xs:string" minOccurs="0" maxOccurs="1" />
more elements here
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
orderservice-order.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xml.xxxxxxxx.com/order"
<xs:element name="order">
<xs:complexType>
<xs:sequence>
<xs:element name="orderNumber" type="xs:string" minOccurs="1" maxOccurs="1" />
more elements here
</xs:sequence>
</xs:complexType>
</xs:element>
jaxbBindings.xjb
<jxb:bindings schemaLocation="../XSD/v1.0/Representation/orderservice-order.xsd">
<jxb:bindings node="//xs:element[#name='order']/xs:complexType">
<jxb:class name="OSOrder" />
</jxb:bindings>
</jxb:bindings>
When I come to create the Java source for these schema files I am obviously getting a class name clash on the Order class.
I've created a jaxb bindings .xjb file to rename the generated Order class name from the orderservice-order.xsd.
However I still get the following error
...XSD/v1.0/Representation/orderservice-order.xsd; lineNumber: 69; columnNumber: 15; 'order' is already defined
It doesn't appear to be a problem with the XPATH in the .xjb file. If I rename the element in orderservice-order.xsd to say orderNew and change the xpath to
node="//xs:element[#name='orderNew']/xs:complexType"
there is obviously no name clash but the class IS renamed to 'OSOrder'
It's as if there is some pre-validation of the schema files PRIOR to the bindings file rename kicking in. I've tried turning off various jaxb/maven settings such as strict validation etc etc but to no avail.
Anybody seen this before and know a way to fix it??? By the way I don't control the content of the schema files.
Thank You
I'm using the maven plugin jaxb2-maven-plugin version 1.3 and jaxb version 2.0 running on Java 7.
maven config
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>Representations</id>
<configuration>
<schemaDirectory>XSD/v1.0/Representation</schemaDirectory>
<packageName>com.xxxxxxxxx.xml.representation.v1</packageName>
<bindingDirectory>XSD/v1.0/Representation</bindingDirectory>
<outputDirectory>src/main/generated-sources</outputDirectory>
<staleFile>${project.build.directory}/generated-sources/jaxb/.representation</staleFile>
<clearOutputDir>false</clearOutputDir>
</configuration>
<goals>
<goal>xjc</goal>
</goals>
</execution>
In your JAXB bindings you can specify bindings for each file if you need and for each file rename the class as you want to resolve conflicts.
Here's an example :
<jxb:bindings schemaLocation="order.xsd">
<jxb:bindings node="//xs:element[#name='order']">
<jxb:class name="Order" implClass="Order"/>
</jxb:bindings>
</jxb:bindings>
<jxb:bindings schemaLocation="orderservice-order.xsd">
<jxb:bindings node="//xs:element[#name='order']">
<jxb:class name="OSOrder" implClass="OSOrder"/>
</jxb:bindings>
</jxb:bindings>
Here's the documentation : http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/tutorial/doc/JAXBUsing4.html
EDIT
I managed to reproduce the problem on my side.
The problem is the target namespace :
targetNamespace="http://xml.xxxxxxxx.com/order"
You have the same target namepace in both XSD.
So you define the type order twice in the same namespace which is not possible.
If you change the target namespace, you won't have the problem anymore.
Example for orderservice-order.xsd, I changed the target namespace into :
targetNamespace="http://xml.xxxxxxxx.com/orderservice-order"
I don't have the problem anymore.

Create Java classes with JaxB

I tried to create Java classes with JaXB from this XSD http://pda.rosreestr.ru/upload/www/files/02_V04_STD_Region_Cadastr_KV.rar but got these errors.
parsing a schema...
[WARNING] Simple type "dAllDocuments" was not mapped to Enum due to EnumMemberSizeCap limit. Facets count: 298, current limit: 256. You can use customization attribute "typesafeEnumMaxMembers" to extend the limit.
line 3 of file:/D:/liferay-develop/workspace/JABX_test/src/02_V04_STD_Region_Cadastr_KV/dAllDocuments.xsd
compiling a schema...
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 1645 of file:/D:/liferay-develop/workspace/JABX_test/src/02_V04_STD_Region_Cadastr_KV/STD_Region_Cadastr_KV.xsd
[ERROR] (Related to above error) This is the other declaration.
line 1587 of file:/D:/liferay-develop/workspace/JABX_test/src/02_V04_STD_Region_Cadastr_KV/STD_Region_Cadastr_KV.xsd
Failed to produce code.
When I work with another schemas everything is fine. I am not good in work with XML, can you tell me what these errors mean and how to solve it?
UPDATE
I tried to use binding.xml in class generation but got this error.
C:\Documents and Settings\kliver\Мои документы\Загрузки\jaxb-ri-2.2.6\bin>xjc -d
out -b binding.xml D:/liferay-develop/workspace/JABX_test/src/02_V04_STD_Region
_Cadastr_KV/STD_Region_Cadastr_KV.xsd
parsing a schema...
[ERROR] "D:/liferay-develop/workspace/JABX_test/src/02_V04_STD_Region_Cadastr_KV
/STD_Region_Cadastr_KV.xsd" is not a part of this compilation. Is this a mistake
for "file:/D:/liferay-develop/workspace/JABX_test/src/02_V04_STD_Region_Cadastr
_KV/STD_Region_Cadastr_KV.xsd"?
line 6 of file:/C:/Documents%20and%20Settings/kliver/%D0%9C%D0%BE%D0%B8%20%D0%
B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B/%D0%97%D0%B0%D0%B3%D1%80%D1%8
3%D0%B7%D0%BA%D0%B8/jaxb-ri-2.2.6/bin/binding.xml
[WARNING] Simple type "dAllDocuments" was not mapped to Enum due to EnumMemberSi
zeCap limit. Facets count: 298, current limit: 256. You can use customization at
tribute "typesafeEnumMaxMembers" to extend the limit.
line 3 of file:/D:/liferay-develop/workspace/JABX_test/src/02_V04_STD_Region_C
adastr_KV/dAllDocuments.xsd
Failed to parse a schema.
UPDATE2
I try this binding:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<!-- Raise theEnumMemberSizeCap limit -->
<jxb:bindings >
<jxb:globalBindings typesafeEnumMaxMembers="2000"/>
</jxb:bindings>
<jxb:bindings schemaLocation="D:\liferay-develop\workspace\JABX_test\src\02_V04_STD_Region_Cadastr_KV\STD_Region_Cadastr_KV.xsd">
<jxb:bindings node="//xs:complexType[#name='tRight_Owner']">
<jxb:class name="tRight_Owner2"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
And this console command:
C:\Documents and Settings\kliver\Мои документы\Загрузки\jaxb-ri-2.2.6\bin>xjc -d
out -b binding.xml D:\liferay-develop\workspace\JABX_test\src\02_V04_STD_Region
_Cadastr_KV\STD_Region_Cadastr_KV.xsd
You can use an external bindings file to specify a different class name for one of the complex types.
binding.xml
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<!-- Raise theEnumMemberSizeCap limit -->
<jxb:bindings >
<jxb:globalBindings typesafeEnumMaxMembers="2000"/>
</jxb:bindings>
<jxb:bindings schemaLocation="your-schema.xsd">
<jxb:bindings node="//xs:complexType[#name='tRight_Owner']">
<jxb:class name="TRight_Owner2"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
The xjc command line would be:
xjc -d out -b binding.xml your-schema.xsd
For those of you coming across this question in later years this method worked for me.
Environment: Netbeans 7.4
Build method: Maven - jaxb2-maven-plugin
Create a folder called xjb in src\main.
In that folder create a file called binding.xjb (or any other .xjb name).
In it:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<!-- Raise theEnumMemberSizeCap limit -->
<jxb:bindings >
<jxb:globalBindings typesafeEnumMaxMembers="2000"/>
</jxb:bindings>
</jxb:bindings>
Note that this is not an alternative solution to Blaise's post.
I'm using version 0.13.0 of the maven-jaxb2-plugin, and I found the correct path to the binding file is:
src/main/resources/binding.xjb
The content is the same as OldCurmudgeon proposed, namely:
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<!-- Raise theEnumMemberSizeCap limit -->
<jxb:bindings>
<jxb:globalBindings typesafeEnumMaxMembers="2000" />
</jxb:bindings>
</jxb:bindings>
You have an issue with your XSD, there are multiple declarations of same name tRight_Owner
line 1587:
<xs:complexType>
<xs:complexContent>
<xs:extension base="tRight_Owner"/>
</xs:complexContent>
</xs:complexType>
line 1645:
<xs:complexType name="tRight_Owner">

JAXB converting XSD to Java classes

When I run the following command:
xjc -b xmlSchema.xjb -d src -p com.q1labs.qa.xmlgenerator.model.generatedxmlclasses xmlSchema.xsd
It creates Java classes however I've found that my root class does not have the correct name and does not have #XmlRootElement which declares it as a root element which means when I use the classes to generate XML it is not formed properly.
XSD Schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified" targetNamespace="http://ibm.org/seleniumframework"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Test" type="sel:TestType" xmlns:sel="http://ibm.org/seleniumframework"/>
<xs:complexType name="TestType">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element type="sel:Option1" name="Option1" xmlns:sel="http://ibm.org/seleniumframework"/>
<xs:element type="sel:Option2" name="Option2" xmlns:sel="http://ibm.org/seleniumframework"/>
<xs:element type="sel:Option3" name="Option3" xmlns:sel="http://ibm.org/seleniumframework"/>
</xs:choice>
</xs:complexType>
This is the output I am getting:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<testType xmlns="http://ibm.org/seleniumframework"/>
Generated classes correspond to complex types. Anonymous complex types that are declared as part of global elements will get an #XmlRootElement annotation. Others will have a #XmlElementDecl annotation generated on the ObjectFactory class. This is because there may be more than one global element that corresponds to the same complex type.
For More Information
http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html

How to generate Java code from an XSD that includes MSFT Serialization: GUID datatypes?

I have used the Jaxme 2 libraries before to generate Java code from .XSD files without a problem. I'm currently encountering a problem generating Java from an XSD file that contains a http://schemas.microsoft.com/2003/10/Serialization/ namespace.
Some sample code from my .XSD is:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/MyMessagingTypes"
xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
<xs:complexType name="MyMessage">
<xs:sequence>
...
<xs:element minOccurs="0" name="MyPlanID" type="ser:guid" />
...
</xs:sequence>
</xs:complexType>
<xs:element name="MyMessage" nillable="true" type="tns:MyMessage" />
</xs:schema>
The Error I'm getting is:
Invalid element: The type {http://schemas.microsoft.com/2003/10/Serialization/}guid is not defined.
Any ideas what the problem is or how I can generate Java code from this xsd?
I don't know where the schema for http://schemas.microsoft.com/2003/10/Serialization/ is located, but you would have to find it, and make sure that Java sees both schemas. Alternatively, you could edit the XSD to include your own GUID type instead.

Categories