JAXB Bindings to schemas in a JAR - java

I'm using the maven jaxb2 plugin to generate Java classes, built from schemas in a jar. However, I'm not sure how to correctly locate to these schemas from a bindings file. If Iextract the schemas from the jar and drop them in the same directory as the bindings, all is well. However, this isn't a practical long term solution.
pom.xml:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemas>
<schema>
<dependencyResource>
<groupId>com.test</groupId>
<artifactId>schemas</artifactId>
<version>1.10-SNAPSHOT</version>
<resource>schemas/schema.xsd</resource>
</dependencyResource>
</schema>
</schemas>
<bindingDirectory>bindings</bindingDirectory>
<generatePackage>test.package</generatePackage>
<bindingIncludes>
<include>*.xml</include>
</bindingIncludes>
<extension>true</extension>
</configuration>
</plugin>
bindings.xml:
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb ./bindingschema_2_1.xsd"
version="2.1">
<jxb:bindings schemaLocation="classpath:/schemas/schema.xsd" node="/xs:schema">
<jxb:bindings node="//xs:complexType[#name='AbstractChangeable']">
<jxb:class implClass="com.test.AbstractEntity" />
</jxb:bindings>
</jxb:bindings>

You need to use maven-dependency-plugin:unpack and then point maven-jaxb2-plugin to outputDirectory. In this case in binding file you need to say something like schemaLocation="../target/schemas/schema.xsd"

What I'd like to have working here is something like:
<jaxb:bindings schemaLocation="maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-po!/purchaseorder.xsd" node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="org.jvnet.jaxb2.maven2.tests.po"/>
</jaxb:schemaBindings>
</jaxb:bindings>
But it does not at the moment. Please file an issue, I'll try to fix it.
What does work now is SCD-based binding:
<jaxb:bindings scd="x-schema::po" xmlns:po="urn:po">
<jaxb:schemaBindings>
<jaxb:package name="org.jvnet.jaxb2.maven2.tests.po"/>
</jaxb:schemaBindings>
</jaxb:bindings>
So you don't actually need to bind based on a specific schema location, you can bind based on the namespace URI, which is theoretically better.
Practically I have an experience that SCD-bindings don't always work reliably.
UPDATE
See this link for more information SCD usage in JAXB.

I know this is an old question but I was struggling with the same problem. I found that doing inline bindings would solve the problem. You would no longer have any need for the binding file and the bindings would be carried over to projects depending on it.

Related

Adding #Generated annotation to JAXB generated classes

I am trying to add a #javax.annotation.Generated annotation to all my classes generated by JAXB from a XSD.
I am using maven-jaxb2-plugin and a binding.xjb file to generate the source. I saw that the JAXB plugin jaxb2-basics-annotate should do the trick. But all I can find are examples that add annotations to specific classes. Like this one:
<jaxb:bindings schemaLocation="csw/2.0.2/CSW-discovery.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[#name='GetRecordsType']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="GetRecordsType" />
</annox:annotate>
</jaxb:bindings>
How can I do this for each of my generated files? Is this possible at all?
It appears you are using highsource/jaxb2-annotate-plugin If you are also using his highsource/maven-jaxb2-plugin, there is builtin support for this feature. Just add this to the plugin configuration:
<configuration>
<markGenerated>true</markGenerated>
</configuration>
Also check controlling the output.
If you are the official jaxb2 plugin, that feature is also builtin
<configuration>
<addGeneratedAnnotation>true</addGeneratedAnnotation>
</configuration>

JAXB/Maven JAX-WS: global bindings.xml references particular WSDL

I'm using Maven JAXWS plugin and bindings.xml file to override a Java type for a JAXB class field generated from a WSDL, but have a problem when generating Java classes from multiple WSDLs with the JAX-WS Maven plugin.
My project structure is:
- src
- jaxws
- bindings.xml
- main
- resources
- wsdl
- Wsdl1.wsdl
- Wsdl1.xsd
- Wsdl2.wsdl
- Wsdl2.xsd
Wsdl1.wsdl references Wsdl1.xsd, Wsdl2.wsdl references Wsdl2.xsd, the two WSDLs and XSD have nothing in common. The WSDLs and XSDs cannot be modified by me.
I want to override the Java type of a particular field (departureDate) in a particular type (Flight) in Wsdl2.xsd.
My bindings.xml is
<bindings version="2.0" extensionBindingPrefixes="xjc"
xmlns="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">
<globalBindings>
<xjc:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
adapter="my.LocalDateAdapter"/>
<xjc:javaType name="org.joda.time.DateTime" xmlType="xs:dateTime"
adapter="my.DateTimeAdapter"/>
</globalBindings>
<bindings schemaLocation="../main/resources/wsdl/Wsdl2.xsd" node="/xs:schema">
<bindings node="//xs:complexType[#name='Flight']//xs:element[#name='departureDate']">
<xjc:javaType name="org.joda.time.LocalDateTime"
adapter="my.LocalDateTimeAdapter"/>
</bindings>
</bindings>
</bindings>
My Maven configuration is
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
</configuration>
</execution>
</executions>
</plugin>
When I build the module with that configuration, JAX-WS processes the WSDLs one by one, but uses the same bindings.xml for each of them. That way, it fails during processing of Wsdl1 due to the reference to Wsdl2.xsd in bindings.xml.
[INFO] --- jaxws-maven-plugin:2.2:wsimport (default) # my-backend ---
[INFO] Processing: file:/D:/dev/Projects/my-api/my-backend/src/main/resources/wsdl/Wsdl1.wsdl
[INFO] jaxws:wsimport args: [-keep, -s, D:\dev\Projects\my-api\my-backend\target\generated-sources\wsimport, -encoding, UTF-8, -Xnocompile, -b, D:\dev\Projects\my-api\my-backend\src\jaxws\bindings.xml, file:/D:/dev/Projects/my-api/my-backend/src/main/resources/wsdl/Wsdl1.wsdl]
parsing WSDL...
[ERROR] "file:/D:/dev/Projects/my-api/my-backend/src/main/resources/wsdl/Wsdl2.xsd"
is not a part of this compilation. Is this a mistake for "file:/D:/dev/Projects/my-api/my-backend/src/main/resources/wsdl/Wsdl1.wsdl#types?schema1"?
line 11 of file:/D:/dev/Projects/my-api/my-backend/src/jaxws/bindings.xml
If I select just Wsdl2.wsdl for processing by the JAX-WS plugin, then all works fine.
<configuration>
<wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
<wsdlFiles>
<wsdlFile>Wsdl2.wsdl</wsdlFile>
</wsdlFiles>
</configuration>
How can I solve this issue?
Create one execution of wsimport for all the WSDLs except Wsdl2.wsdl and another execution for Wsdl2.wsdl. This way you can have different configurations for each execution and specify the jaxb bindings for each differently.

Getting a list of JAXBElement where I want a list of predefined java objects

I use Apache Camel + JAXB for Soap processing. The java glasses are generated by a maven plugin called cxf-codegen-plugin.
The Problem I am facing is that when I want to use a property which is a list. In that case I will always get a list of JAXBElement instead of objects of the correct class.
Assume this given xml snipped:
<domainObjects avqxsi:type="avqsq:AssetAllocation" id="100" name="Some Name">
<nodes>101</nodes>
<nodes>102</nodes>
</domainObjects>
Now all the "nodes" are ids of different domain objects of type AANode. So in the xsd it is defined like so:
<xsd:complexType name="AssetAllocation">
<xsd:complexContent>
<xsd:extension base="avqsq:DomainObject">
<xsd:sequence>
<xsd:element ecore:reference="avqsq:AANode" maxOccurs="unbounded" name="nodes" type="xsd:IDREF"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
And I have defined some bindings.xml:
<jaxb:bindings node="xsd:complexType[#name='AssetAllocation']//xsd:element[#name='nodes']">
<jaxb:property>
<jaxb:baseType name="my.api.xsd.AANode"/>
</jaxb:property>
</jaxb:bindings>
What I want is a POJO property like this:
#XmlElementRef(name = "nodes")
protected List<AANode> nodes;
But what I actually get at runtime is a List<JAXBElement<AANode>> which leads into a ClassCastException.
EDIT 1:
I have missed the fact that the cxf-codegen framework is generating a class where you clearly can see that the property is annotated with JAXBElement.class which i think is wrong. Interestingly changing the annotation by hand to AANode.class will fail with an IllegalAnnotationException: AANode" or any of its subclasses are not known to this context.
public class AssetAllocation
extends DomainObject
implements Serializable, Equals, HashCode, ToString
{
#XmlElementRef(name = "nodes", type = JAXBElement.class)
protected List<AANode> nodes;
apache CXF code gen plugin will always generate codes with JAXBElement until you set the generate element property flag.
Please create Jaxb binding.xml and refer that binding xml in your code gen plugin section from pom file as below
binding.xml
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings version="2.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
<jaxb:bindings>
<jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>
</jaxb:bindings>
code gen plugin
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>wsdl2java</goal>
</goals>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/META-INF/wsdl/CxfExampleService.wsdl</wsdl>
<bindingFiles>
<bindingFile>${basedir}/src/main/resources/META-INF/wsdl/binding/bindings.xml</bindingFile>
</bindingFiles>
</wsdlOption>
</wsdlOptions>
</configuration>
</execution>
</executions>
</plugin>
This will resolve the issue
In fact the wsdl2java generates classes with wrong annotations. Instead of
#XmlElementRef(name = "nodes", type = JAXBElement.class)
protected List<AANode> nodes;
One would expect to have:
#XmlIDREF
protected List<AANode> nodes;
I was not able to manage this by bindings.xml. So my final solution is that I use a Byte-Code manipulation to fix the annotations. That way I do not have to mess around with the generated classes or with the generator itself.

Jaxb doesn't preserve case of namespace in package

I'm using the codehaus jaxb2-maven-plugin, v1.5 to compile XSDs into POJOs, but the generated package name coerces the package name to lower case (so, if I have my target namespace as http://example.com/sampleNamespace, then the generated package is com.example.samplenamespace).
I've googled around a bit and found mostly people having problems with underscores getting munged to dots, and the solution for that, but I can't seem to find something specific for preserving the case of the namespace.
NB: I don't want to have to repeat myself and override the generated package name, so the generatePackage option in the maven config isn't for me.
Before finding about the underscore munging, I had tried that, and also a regular space - both stick a dot in there.
Any ideas?
Schema:
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:t="http://example.com/sampleNamespace" targetNamespace="http://example.com/sampleNamespace"
jaxb:version="2.0">
<complexType name="MyFirstClass">
<sequence>
<element name="MyFirstElement" type="string" />
</sequence>
</complexType>
</schema>
Maven config:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
</plugin>
You will need to leverage a JAXB bindings file to specify a package name if you do not want to use the one that JAXB generates based on common Java coding conversions.
<bindings
xmlns="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<bindings schemaLocation="schema.xsd">
<schemaBindings>
<package name="com.example.sampleNamespace"/>
</schemaBindings>
</bindings>
</bindings>

Can't use jaxb bindings on individual xsd elements

I'm using jaxb to generate java source code from an xsd file.
I want to be able to specify which packages the sources are generated in on a per element basis, however whenever I generate sources I get the following error:
[ERROR] ****/src/main/xjb/common.xjb[8,24]
com.sun.istack.SAXParseException2: compiler was unable to honor this schemaBinding customization. It is attached to a wrong place, or its inconsistent with other bindings.
My bindings file common.xjb is attempting to place the element with the name (attribute value) 'api' in the package 'com.myxml.common.api':
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="../xsd/common/common.xsd" node="/xs:schema">
<jxb:bindings node="//xs:element[#name='api']">
<jxb:schemaBindings>
<jxb:package name="com.myxml.common.api" />
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
My xsd file common.xsd is:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1" xml:lang="en">
<xs:element name='api'>
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
And I'm using the following Maven plugin to get everything going:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>schema00-generate</id>
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<schemaFiles>common/common.xsd</schemaFiles>
<bindingFiles>common.xjb</bindingFiles>
<bindingDirectory>${project.basedir}/src/main/xjb</bindingDirectory>
</configuration>
</execution>
</executions>
</plugin>
Why am I getting this error and how can I resolve it? I don't have any other bindings in use at this stage that I'm aware of.
Elements from the same namespace cannot be mapped to different packages so the package cannot be defined for anything other than the top level

Categories

Resources