JAXB Duplicate class renaming - java

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.

Related

JAXB2 Maven Plugin xjc parse error: org.xml.sax.SAXParseException: Unexpected <xs:element> appears

I want to use JAXB2 maven plugin to generate Java Objects from WSDL file to consume a soap service as a client.
When I use this plugin as "jaxb2:generate" and configuration below:
...
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.14.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>tr.com.foo.dummy.model</generatePackage>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
<bindingDirectory>${project.basedir}/src/main/resources</bindingDirectory>
<bindingIncludes>
<bindingInclude>*.xjb</bindingInclude>
</bindingIncludes>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
</configuration>
</plugin>
...
I get an error saying:
[INFO] --- maven-jaxb2-plugin:0.14.0:generate (default-cli) # hmbs ---
[INFO] Latest timestamp of the source resources is [2020-03-13 18:10:23.000], earliest timestamp of the target resources is [2020-03-06 18:06:36.000].
[INFO] Sources are not up-to-date, XJC will be executed.
[ERROR] Error while parsing schema(s).Location [ file:/home/yigithan/playground/foo/bar/src/main/resources/wsdl/foo.wsdl{23,87}].
org.xml.sax.SAXParseException: Unexpected <xs:element> appears at line 23 column 87
...
And my WSDL file is like:
<?xml version="1.0" encoding="utf-8" ?>
<wsdl:definitions xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s1="http://tempuri.org/AbstractTypes"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/" version="1.0">
<xs:element name="Insert">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="custom" type="tns:Custom"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Custom">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="foo" type="xs:int"/>
<xs:element minOccurs="1" maxOccurs="1" name="bar" type="xs:int"/>
<xs:element minOccurs="1" maxOccurs="1" name="baz" type="xs:long"/> 
<xs:element minOccurs="1" maxOccurs="1" name="qux" type="xs:dateTime"/>
</xs:sequence>
</xs:complexType>
...
And the error location is in the line that contains "qux" element and {23, 87} point is the type="xs:dateTime" of "qux". As you can see there is no element that is unexpected. Or am I missing some point?
Okay, I have solved the problem. It was a really long road to solution. Two problems occured. The first one, which is the reason that i asked this question at the first place is, the WSDL file was sent to me as a DOCX file and reformat of file is needed even if i copy-pasted content of the file inside of a WSDL file. By reformat I am not telling about xml structure. It was like a joke but removing blank lines and reintend the file worked.
The next problem occurs as "unexpected sequence" in a place like:
<s:schema targetNamespace="http://tempuri.org/AbstractTypes">
<s:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<s:complexType name="StringArray">
<s:complexContent>
<s:restriction base="soapenc:Array">
<s:sequence>
<s:element maxOccurs="unbounded" minOccurs="0" name="String" type="s:string"/>
</s:sequence>
</s:restriction>
</s:complexContent>
</s:complexType>
</s:schema>
And the reason for it is JAXB2 can not handle encoded types according to my research. So, if an unrelated error occurs, first try to refactor xml file in case of misconstruction of xml and then make sure plugin is compatible with the types you are using.
The maven-jaxrpc-plugin is working well in this situation.
NOTE: R2110 In a DESCRIPTION, declarations MUST NOT extend or restrict the soapenc:Array type.

Customize element for abstract complexType with HyperJaxb3

I'm converting an XSD schema to a Java annotated bean for Hibernate with HyperJaxb3.
So far I managed to generate the Java objects, but I need to customize the remark field of the OperableType because the default generated length is 255 and I need to extend it to 4000.
Here's the fragment of the relevent xsd schema:
<xs:complexType name="OperableType" abstract="true">
<xs:annotation>
<xs:documentation xml:lang="en">OperableType contains all the elements and attributes common to all the operables. This is an abstract type, so no element of this type will be present in the XML.
The logical ID is a unique logical identifier of a sanctioned entity, of a regulation or of a detail of a sanction entity. This information is also provided to external actors for help, especially when entity multiple aliases make it difficult the identification task. For entities imported from previous database, the old value is retained.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="remark" type="fsdexport:UnlimitedTextType" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="additionalInformation" type="fsdexport:AdditionalInfoType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="logicalId" type="xs:long" use="required"/>
</xs:complexType>
<xs:simpleType name="UnlimitedTextType">
<xs:restriction base="xs:string"/>
</xs:simpleType>
I can't modify the XSD schema nor the XML file I receive, so I need to customize the bindings for it to work.
I tried using this binding
<jxb:bindings node="xs:complexType[#name='OperableType']">
<jxb:bindings node="xs:sequence//xs:element[#name='remark']">
<hj:basic>
<orm:column length="4000" />
</hj:basic>
</jxb:bindings>
</jxb:bindings>
but it doesn't modify the length in the generated code.
#ElementCollection
#OrderColumn(name = "HJINDEX")
#Column(name = "HJVALUE", length = 255)
#CollectionTable(name = "OPERABLE_TYPE_REMARK", joinColumns = {
#JoinColumn(name = "HJID")
})
public List<String> getRemark() {
I also tried to use 'hj:default-single-property' to customized the UnlimitedTextType but I didn't managed to make it work either.
After asking from help from the source,
https://github.com/highsource/hyperjaxb3/issues/54, I have the answer:
<jxb:bindings node="xs:complexType[#name='OperableType']">
<jxb:bindings node="xs:sequence//xs:element[#name='remark']">
<hj:element-collection>
<orm:column length="4000" />
</hj:element-collection>
</jxb:bindings>
</jxb:bindings>
The key is tu use hj:element-collection instead of hj:basic for an xml sequence.

JAXB/XJC external binding for renaming versus multiple XSD compile

(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.

How to override default name in JAXB using external binding?

I am trying to use JAXB to convert xsd schema to java classes. Unfortunately I do have an issue. The xsd which casues problem is:
<xs:complexType name="AdditionalDataType">
<xs:sequence>
<xs:element name="AvailabilityStatus" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="AvailabilityStatus" maxOccurs="999">
<xs:complexType>
<xs:attributeGroup ref="IdentifierGrp"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
The error I get is
[ERROR] \target\generated-sources\AdditionalDataType.java:[1012,22] AdditionalDataType.AvailabilityStatus is already defined in AdditionalDataType
I found this How to override the default name for in JAXB using a external binding file?
but when I tried to solve it with the following bindings:
<jxb:bindings node="//xs:complexType[#name='AdditionalDataType']//xs:sequence//xs:element[#name='AvailabilityStatus']//xs:complexType//xs:sequence//xs:element[#name='AvailabilityStatus']">
<jxb:property name="AvailabilityStatusSA"/>
</jxb:bindings>
it didn't help, it didn't change anything.
Can someone please help ?
#Ekrem
I cannot modify the xml, I would do it but I cannot. I need to have AdditionalDataType which has a List of AvailabilityStatus
I dont care if the inner AvailabilityStatus (the one I am trying to map to AvailabilityStatusSA) will be an inner class or not.
Change
<jxb:property name="AvailabilityStatusSA"/> to <jxb:class name="AvailabilityStatusSA"/> and your binding node path should end with complexType -><jxb:bindings node=...[#name='AvailabilityStatus']xs:complexType"
so your external binding file should look like this:
<jxb:bindings node="//xs:complexType[#name='AdditionalDataType']//xs:sequence//xs:element[#name='AvailabilityStatus']//xs:complexType//xs:sequence//xs:element[#name='AvailabilityStatus']//xs:complexType">
<jxb:class name="AvailabilityStatusSA"/>
</jxb:bindings>

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