Generate java classes from xsd with jaxb from a choice - java

I use maven with jaxb to make classes out from a schema. This schema has the following choice:
<tns:choice minOccurs="1" maxOccurs="unbounded">
<tns:element name="video_track" type="tcore:TTrack" minOccurs="1" maxOccurs="1"/>
<tns:element name="audio_track" type="tcore:TTrack" minOccurs="1" maxOccurs="1"/>
</tns:choice>
The meening is, we want a list with x audiotracks and/or x videotracks. We need at least one of an audio or a video track!
When I generate classes with this choice I get the following code:
#XmlElementRefs({
#XmlElementRef(name = "audio_track", type = JAXBElement.class),
#XmlElementRef(name = "video_track", type = JAXBElement.class)
})
protected List<JAXBElement<TTrack>> videoTrackOrAudioTrack;
This is not what we want. I think I loose informations because with the list of TTracks I don't know if this is a video or an audio.
So what am I doing wrong here?
In maven I use org.jvnet.jaxb2.maven2 version 0.8.3

No, you don't lose this information.
You get a list of JAXBElement<TTrack>. So you can check e.getName() to find out if it is an audio or a video track.
You can use my Simplify plugin to get audio and video tracks in separate properties. This is not exactly the model you have in your schema, but pretty close and much easier to use.
This customization:
<xs:complexType name="typeWithReferencesProperty">
<xs:choice maxOccurs="unbounded">
<xs:element name="a" type="someType">
<xs:annotation>
<xs:appinfo>
<simplify:as-element-property/>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="b" type="someType"/>
</xs:choice>
</xs:complexType>
Produces:
#XmlElement(name = "a")
protected List<SomeType> a;
#XmlElement(name = "b")
protected List<SomeType> b;
The reason you get this model is the maxOccurs on your choice.
Also consider using xs: or xsd: prefixes for your XML Schema.

I resolved the problem with the simplify approach in a .xjb file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="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" version="2.1" xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify" extensionBindingPrefixes="simplify">
<jaxb:bindings schemaLocation="http://xxx/Core.xsd">
<jaxb:bindings node="/xs:schema/xs:complexType[#name='TStreamRecorder']/xs:sequence/xs:choice/xs:element[1]">
<simplify:as-element-property />
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
To activate this plugin i changed my maven .pom file to:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<executions>
<execution>
<id>process-xsd</id>
<goals>
<goal>generate</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<args>
<arg>-Xsimplify</arg>
<arg>-Xannotate</arg>
</args>
<schemas>
<schema>
<url>http://xxxConfiguration.xsd</url>
</schema>
</schemas>
<bindingIncludes>
<include>schema/configBinding.xjb</include>
<include>schema/coreBinding.xjb</include>
</bindingIncludes>
</configuration>
</execution>
</executions>
</plugin>
This works perfect for me

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.

cxf codegen-plugin generating List of JAXBElement even if generateElementProperty=false

i'm using cxf-codegen-plugin wsdl2java with the following binding file:
<jaxb:bindings version="2.1"
xmlns:jaxb="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">
<jaxb:bindings>
<jaxb:globalBindings generateElementProperty="false">
</jaxb:globalBindings>
</jaxb:bindings>
</jaxb:bindings>
My problem is the following section of my xsd
<xs:complexType name="clientType">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" />
<xs:choice>
<xs:sequence>
<xs:element name="phone1" type="xs:string"
minOccurs="1" />
<xs:element name="phon2" type="xs:string"
minOccurs="0" />
</xs:sequence>
<xs:element name="phone2" type="xs:string"
minOccurs="1" />
</xs:choice>
</xs:sequence>
</xs:complexType>
I still get a list of
protected List<JAXBElement<String>> content;
and my ClientType class is annotated with
#XmlElementRefs({
#XmlElementRef(name = "name", type = JAXBElement.class, required = false),
#XmlElementRef(name = "phone1", type = JAXBElement.class, required = false),
#XmlElementRef(name = "phone2", type = JAXBElement.class, required = false)
})
EDIT: the codegen plugin
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<defaultOptions>
<bindingFiles>
<bindingFile>${basedir}/src/main/jaxb/bindings.xml</bindingFile>
</bindingFiles>
<noAddressBinding>true</noAddressBinding>
</defaultOptions>
<configuration>
<sourceRoot>${basedir}/src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/service.wsdl</wsdl>
<extraargs>
<extraarg>-server</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
Is there a way to avoid having list of JAXBElement instead of list of String ?
Thanks

How to generate classes using maven jaxb implements serializable

I want my all xjc generated classes implementing serializable interface.
After reading solution at post I implemented it but jaxb2-maven-plugin throws below error:
[ERROR] file: mapping.xsd [17,34] org.xml.sax.SAXParseException;
systemId: file:mapping.xsd; lineNumber: 17; columnNumber: 34;
src-annotation: elements can only contain and
elements, but 'globalBindings' was found. at
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
at
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
at
My xsd sample:
<xs:schema 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"
attributeFormDefault="unqualified"
elementFormDefault="qualified">
<xs:element name="MappingFile" type="MappingFileType">
<xs:annotation>
<jaxb:globalBindings>
<xjc:serializable uid="43538530765l"/>
</jaxb:globalBindings>
</xs:annotation>
Maven plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.3</version>
<configuration>
<sources>
<source>xxxx/yyy/mapping.xsd</source>
</sources>
<packageName>xx.yy.zz.jaxp</packageName>
</configuration>
</plugin>
Is there any dependency that i need to use to avoid this exception? Please sugest.
Your binding file should look like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jaxb:globalBindings>
<xjc:serializable uid="1" />
</jaxb:globalBindings>
</jaxb:bindings>
Moreover, touch your binding file in a specific directory and reference it in the maven plugin specific configuration.
Example:
<configuration>
<sources>
<source>src/main/xjb/xsd</source>
</sources>
<packageName>xx.yy.zz.jaxp</packageName>
<xjbSources>
<xjbSource>src/main/xjb/jaxb-bindings.xjb</xjbSource>
</xjbSources>
</configuration>

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.

wsimport - Two declarations cause a collision, same line given

Trying to use wsimport to generate a client for a SOAP endpoint. The WSDL and all XSD files used are local copies.
This is the command being executed:
wsimport ./bwWsdl.xml -p com.generated -Xnocompile -d ../src -extension -keep -XadditionalHeaders -B-XautoNameResolution
Which gives this error:
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 16 of file:/schemas/newSchema.xsd
[ERROR] (Related to above error) This is the other declaration.
line 16 of file:/schemas/newSchema.xsd
Note the line number is the same for the reported collision.
Here's the schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
version="2.004" id="OTA2003A2009A">
<xs:complexType name="TPA_ExtensionsType">
<xs:annotation>
<xs:documentation xml:lang="en">Description here.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:element name="TPA_Extensions" type="TPA_ExtensionsType">
<xs:annotation>
<xs:documentation xml:lang="en">More description here.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>
I've tried removing the type definition, but it's referenced in a slew of other places.
Could anyone please offer any advice for how to get this to work?
Thanks
Edit:
Here's the lines where the WSDL imports these schemas:
<definitions name='ResLookupGet' targetNamespace='http://org.jboss.ws/resLookupGet' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:http='http://schemas.xmlsoap.org/wsdl/http/' xmlns:mime='http://schemas.xmlsoap.org/wsdl/mime/' xmlns:ns='http://www.opentravel.org/OTA/2003/05/beta' xmlns:rq='http://www.opentravel.org/OTA/2003/05/betarq' xmlns:rs='http://www.opentravel.org/OTA/2003/05/betars' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://org.jboss.ws/resLookupGet' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<types>
<xsd:schema targetNamespace='http://org.jboss.ws/resLookupGet' xmlns:tns='http://org.jboss.ws/resLookupGet' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betarq' schemaLocation='./schemas/FooAffiliateHeaderRQ.xsd'/>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betarq' schemaLocation='./schemas/FooResLookupGetRQ.xsd'/>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betars' schemaLocation='./schemas/FooResLookupGetRS.xsd'/>
</xsd:schema>
</types>
<message name='ResLookupGetRQ'>
<part element='rq:FooResLookupGetRQ' name='FooResLookupGetRQ'></part>
</message>
<message name='ResLookupGetRS'>
<part element='rs:FooResLookupGetRS' name='FooResLookupGetRS'></part>
</message>
Thanks to the help of #Petru Gardea I was able to eventually get past this by omitting the -p com.generated package specification to wsimport. So this is what I was eventually able to run to get past this problem:
wsimport ./bwWsdl.xml -Xnocompile -d ../src -extension -keep -XadditionalHeaders -B-XautoNameResolution
The reasoning for it is wsimport is trying to generate classes in the same package with the same name and/or methods, which it obviously cannot do.
So by omitting the forced package declaration, wsimport is able to put the classes in whatever packages it wants, which turns out to be 3 different packages per the <xsd:schema> definition in the WSDL.
Thanks again #Petru!
I had the same issue and I was calling webservice through pom.xml. I just removed packageName and defined a sourceDestDir. This will create stubs inside source packages. I am taking wsdlURL from a config. Here are the changes I did in pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>wsimport-from-jdk</id>
<goals>
<goal>wsimport</goal>
</goals>
</execution>
</executions>
<configuration>
<args>
<arg>-B-XautoNameResolution</arg>
</args>
<wsdlUrls>
<wsdlUrl>${service.wsdl.url}</wsdlUrl>
</wsdlUrls>
<keep>true</keep>
<sourceDestDir>src/main/java</sourceDestDir>
</configuration>
</plugin>

Categories