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

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.

Related

jaxb2-maven-plugin generating package-info.java with xmlns prefixes

I want to generate java classes with the jaxb2-maven-plugin. I am using the following configuration:
pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>SomeID</id>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<extension>true</extension>
<clearOutputDir>true</clearOutputDir>
<sources>
<source>src/main/xsd/schema.xsd</source>
</sources>
<noGeneratedHeaderComments>true</noGeneratedHeaderComments>
</configuration>
</execution>
</executions>
</plugin>
schema.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://my.target.namespace/uri"
xmlns="http://my.target.namespace/uri"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:h="http://my.uri.for.prefix.h"
xmlns:f="http://my.target.namespace/uri">
<xsd:import namespace="http://my.uri.for.prefix.h" schemaLocation="schema2.xsd"/>
<xsd:complexType name="FooType">
<xsd:sequence>
<xsd:element ref="h:something" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="FooType" type="FooType" />
</xsd:schema>
The Jaxb2 plugin is generating me the following package-info.java:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://my.target.namespace/uri", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package ...;
But, what I want to get is this:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://my.target.namespace/uri", xmlns = {
#XmlNs(prefix="f", namespaceURI="http://my.target.namespace/uri"),
#XmlNs(prefix="h", namespaceURI="http://my.uri.for.prefix.h")
}, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package ...;
import javax.xml.bind.annotation.XmlNs;
The prefixes are missing in my generated file. How to do that? I tried already to create a binding file but this didn't worked how I expected.
Please see this answer on how to solve this problem:
https://stackoverflow.com/a/10812236/1389219
The answer is very well written and easy to follow. Basically you will have to:
Drop jaxb2-maven-plugin in favour of maven-jaxb2-plugin.
Include the jaxb2-namespace-prefix dependency and provide the <arg>-Xnamespace-prefix</arg>.
Write a new bindings.xml file which is only a few lines long.
Your POM file will become more verbose, but it is worth it to have a package-info.java generated the way you require.
As a bonus, there are a heap of additional plugins and dependencies related to maven-jaxb2-plugin that provide extra features. One that I found helpful was jaxb2-rich-contract-plugin that gave the ability to generate builders and make the generated classes immutable*.
* Well, not strictly speaking immutable (as it just changes the setter methods to be package private), but enough to make them feel safer.

Change XMLGregorianCalendar to Date using external binding file (XJB)

In my maven project, I want all my datetime entries should be generated as java.util.date instead of XMLGregorianCalendar. As you might know XMLGregorianCalendar gets generated by default.
We can take example project provided here.
Here in the CustomersOrders.xsd, you can see attriute ShippedDate is of type dateTime.
<xs:attribute name='ShippedDate' type='xs:dateTime' />
To convert its data type into java.util.date, I'm following approach provided in documentation here. i.e. by using external binding file, like:
Customer.xjb
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings>
<javaType name="java.util.date" xmlType="xs:datetime"
parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
printMethod="javax.xml.bind.DatatypeConverter.printDate"
/>
</globalBindings>
</bindings>
Then I mapped Customer.xjb file in pom.xml like:
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- the package for the generated java classes -->
<generatePackage>com.dimitrisli.jaxb.producedClasses</generatePackage>
<!-- If the following not specified all xsd in resources are included -->
<schemaIncludes>
<include>sampleJaxb/CustomersOrders.xsd</include>
</schemaIncludes>
<!-- if you don't want old output -->
<removeOldOutput>true</removeOldOutput>
<!-- if you want verbosity -->
<!-- verbose>true</verbose -->
<xjbSources>
<xjbSource>sampleJaxb/Customers.xjb</xjbSource>
</xjbSources>
</configuration>
</execution>
</executions>
But when I do mvn clean install, I'm still not able to see any difference in ShippedDate, which is still being generated as XMLGregorianCalendar.
Please suggest what am I missing.
Thank You
If you use the org.jvnet.jaxb2.maven2:maven-jaxb2-plugin then you should use bindingIncludes instead of xjbSources (it's for org.codehaus.mojo:jaxb2-maven-plugin).
<bindingIncludes>
<include>sampleJaxb/Customers.xjb</include>
</bindingIncludes>`
Also, you have to implement a custom adapter for java.util.Date like you have seen in the tutorial or convert to java.util.Calendar:
<javaType name="java.util.Calendar" xmlType="xsd:dateTime"
parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />`
Hope it helps!

JAX-WS service implementation class name customization not working

I'm using Maven to generate the implementation code for a web service. Originally, this code was generated from a WSDL and schema using something else (probably a wizard in Eclipse). The service implementation class name that jaxws-maven-plugin generates is MyService_MyServieSOAPImpl. When this was originally generated, the implementation class was named MyService_SOAPImplementation. I'm guessing that the wizard that Eclipse uses allows the user to choose the name of the implementation class. I tried using the sei element, but it does not work. Here's a snippet of the wsimport plugin in my POM:
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<id>generateMyServiceFromWSDL</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<genJWS>true</genJWS>
<bindingDirectory>${basedir}/src/main/bindings</bindingDirectory>
<bindingFiles>
<bindingFile>otherSchema.episode</bindingFile>
</bindingFiles>
<wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
<wsdlFiles>
<wsdlFile>MyService.wsdl</wsdlFile>
</wsdlFiles>
<wsdlLocation>${project.basedir}/src/main/resources/wsdl/MyService.wsdl</wsdlLocation>
<sourceDestDir>${project.basedir}/src/main/java</sourceDestDir>
<sei>com.myCompany.MyService_SOAPImplementation</sei>
<xdonotoverwrite>true</xdonotoverwrite>
<xnocompile>true</xnocompile>
<xdebug>true</xdebug>
<verbose>true</verbose>
<target>2.0</target>
</configuration
</execution>
...
From some of the documents I've read, it looks like sei is only applicable for wsgen, not wsimport. If that is so, is there any way to force a name for the implementation class name?
UPDATE
Ok, so from my reading, it should be possible to do this with a JAX-WS binding file, not directly in the POM file.
I've created my binding file like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxws:bindings version="2.1" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
jaxws:wsdlLocation="src/main/webapp/wsdl/MyService.wsdl">
<jaxws:bindings node="wsdl:definitions/wsdl:portType[#name='MyService']">
<!-- change the generated SEI class -->
<jxb:class name="MyServiceSOAPImpl"></jxb:class>
</jaxws:bindings>
</jaxws:bindings>
But this still doesn't seem to have any effect - wsimport is still producing the implementation as MyService_MyServiceSOAPImpl.
Try changing your
<jaxws:bindings node="wsdl:definitions/wsdl:portType[#name='MyService']">
to
<jaxws:bindings node="wsdl:definitions/wsdl:service[#name='MyServiceService']">
Note that the second part of the node path is service and not portType. You would use portType to customize the service interface, not the implementation.
As an aside it's important to note that JAX-WS bindings (seemingly) need to be in their own XML file (per WSDL) and not included with JAXB bindings.
Someone may find the list of JAX-WS bindings here to be useful: http://docs.oracle.com/cd/E13222_01/wls/docs103/webserv/data_types.html#wp227312
In case this helps someone, two changes are required in OPs bindings.xml file to get it to work:
The first change was already suggested by MGE - changing the wsdl:portType in the Xpath to wsdl:service
The namespace for class name has to be 'jaxws', so
change to this:
<jaxws:class name="MyServiceSOAPImpl"/>
from
<jxb:class name="MyServiceSOAPImpl"></jxb:class>

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>

JAXB Bindings to schemas in a JAR

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.

Categories

Resources