JAXB - The schemaBindings customization is not associated with any schema element - jaxb

I'm trying to generated Java classes from a set of XSD files using the Maven XJC plugin with a custom binding. The customization is added to prefix JAXB generated classes. When the maven build runs, however, the XJC plugin doesn't seem to recognize the schemaBindings element and throws the exception as under.
[ERROR] Error while parsing schema(s).Location [ file:/C:/blah/bindings.xjb{5,25}].
com.sun.istack.SAXParseException2: The "jaxb:schemaBindings" customization is no
t associated with any schema element.
at com.sun.tools.xjc.reader.internalizer.Internalizer.reportError(Intern
alizer.java:632)
at com.sun.tools.xjc.reader.internalizer.Internalizer.reportError(Intern
alizer.java:626)
at com.sun.tools.xjc.reader.internalizer.Internalizer.move(Internalizer.
java:451)
at com.sun.tools.xjc.reader.internalizer.Internalizer.transform(Internal
izer.java:160)
at com.sun.tools.xjc.reader.internalizer.Internalizer.transform(Internal
izer.java:109)
at com.sun.tools.xjc.reader.internalizer.DOMForest.transform(DOMForest.j
ava:449)
at com.sun.tools.xjc.ModelLoader.buildDOMForest(ModelLoader.java:345)
at com.sun.tools.xjc.ModelLoader.loadXMLSchema(ModelLoader.java:377)
at com.sun.tools.xjc.ModelLoader.load(ModelLoader.java:174)
at com.sun.tools.xjc.ModelLoader.load(ModelLoader.java:119)
at org.jvnet.mjiip.v_2_2.XJC22Mojo.loadModel(XJC22Mojo.java:45)
at org.jvnet.mjiip.v_2_2.XJC22Mojo.doExecute(XJC22Mojo.java:35)
at org.jvnet.mjiip.v_2_2.XJC22Mojo.doExecute(XJC22Mojo.java:22)
at org.jvnet.jaxb2.maven2.RawXJC2Mojo.doExecute(RawXJC2Mojo.java:282)
at org.jvnet.jaxb2.maven2.RawXJC2Mojo.execute(RawXJC2Mojo.java:147)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPlugi
nManager.java:490)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(Defa
ultLifecycleExecutor.java:694)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLi
fecycle(DefaultLifecycleExecutor.java:556)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(Defau
ltLifecycleExecutor.java:535)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHan
dleFailures(DefaultLifecycleExecutor.java:387)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegmen
ts(DefaultLifecycleExecutor.java:348)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLi
fecycleExecutor.java:180)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:6
0)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
The bindings.jxb is as follows.
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
jaxb:version="2.1" schemaLocation="blah.xsd">
<jaxb:schemaBindings>
<jaxb:nameXmlTransform>
<jaxb:elementName suffix="Type"/>
</jaxb:nameXmlTransform>
</jaxb:schemaBindings>
</jaxb:bindings>
The following plugins are used for the generating the Java Classes. Pasting the relevant mvn snippet here.
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.6</version>
</dependency>
</dependencies>
<configuration>
<schemaDirectory>./src/main/resources</schemaDirectory>
<includeBindings>
<includeBinding>**/*.xjb</includeBinding>
</includeBindings>
<extension>true</extension>
</configuration>
</plugin>
The only other discussion I could find on this issue revolves about JAX-WS which I don't use as there's no WSDL files involved here. It's all XSD files here.
I don't see why this error has to occur because the JAXB's binding.xsd file indeed defines the schemaBindings element as seen below.
<xs:element name="schemaBindings" substitutionGroup="jaxb:declaration">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" ref="jaxb:package"/>
<xs:element minOccurs="0" ref="jaxb:nameXmlTransform"/>
</xs:sequence>
<xs:attribute name="map" type="xs:boolean" />
</xs:complexType>
</xs:element>
Any hints on this problem would be very much appreciated. Please let me know if more inputs are needed. Thanks!
EDIT:
A lot of people on the Internet seem to have used the schemaBindings without any issues. May be this is an issue with the dependencies mentioned in the question?

Your jaxb:schemaBindings must associate bindings with a certain schema schema. Via schema location or scd.
Please see http://jaxb.java.net/guide/Customizing_Java_packages.html

Related

"private final static long serialVersionUID" in JAXB generated class

I am using globalBindings in JAXB to generate Serializable classes.
<jaxb:globalBindings>
<xjc:simple />
<xjc:serializable uid="1" />
</jaxb:globalBindings>
The uid attribute is generated in the java classes as the following:
private final static long serialVersionUID = 1L;
I understand that "final static" and "static final" are the same and the generated serializable classes can also be compiled. But we are getting error from SonarQube of using "final static" instead of "static final".
We are currently manually changing the attribute to "static final" to bypass the SonarQube issue. But can anyone suggest if it is possible to have JAXB to generate "static final" instead?
We are using JAXB2 and this is the pom.xml.
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.3.1</version>
<dependencies>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
<execution>
<id>someID</id>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<sources>
<source>${project.basedir}/src/main/resources/some.xsd</source>
</sources>
<xjbSources>
<xjbSource>src/main/resources/some.xjb</xjbSource>
</xjbSources>
</configuration>
</execution>
From my point of view, it is not really reasonable to check the generated code.
If SonarQube complains about private final static but not private static final, just ignore it. It does not matter, especially not in the generated code.
Now, to answer your question - you can write an XJC plugin which would generate static final instead. Here's an article on it. You can find further examples in JAXB2 Basics.
Disclaimer: I am the author of JAXB2 Basics which is a package of XJC plugins.

Jaxb2-annotate-plugin does not work with episodes

I am trying to enforce enum validation for my generated JAXB classes, but I am having some issues with getting them bound.
The basic XSD setup is:
-enumsXSD
-2 other XSDs that import this XSD
To provent duplication of my classes I am using episodes, but it looks like this does not play nice when adding annotions in the enumsXSD
com.sun.istack.SAXParseException2: compiler was unable to honor this annox:annotateEnumValueMethod customization. It is attached to a wrong place, or its inconsistent with other bindings.
[ERROR] Error while generating code.Location [ file:somewhere/generic.episode{64,99}].
com.sun.istack.SAXParseException2: (the above customization is attached to the following location in the schema)
The code:
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.3</version>
<configuration>
<extension>true</extension>
<args>
<arg>-Xannotate</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>1.0.4</version>
</plugin>
</plugins>
</configuration>
<executions>
<!--GENERIC ENUMS -->
<execution>
<id>ENUMS</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<extension>true</extension>
<generatePackage>com.foo.generic.enums</generatePackage>
<generateDirectory>${project.build.directory}/generated-sources/xjc1/generic</generateDirectory>
<!-- Define the directory where we should find the XSD files -->
<schemaDirectory>
src/main/resources/dtd/generic
</schemaDirectory>
<schemaIncludes>
<source>enums.xsd</source>
</schemaIncludes>
<episodeFile>
${project.build.directory}/generated-sources/xjc1/generic/META-INF/generic.episode
</episodeFile>
</configuration>
</execution>
<execution>
<id>A_XSD</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<extension>true</extension>
<bindingDirectory>${project.build.directory}/generated-sources/xjc1/generic/META-INF</bindingDirectory>
<bindingIncludes>
<include>generic.episode</include>
</bindingIncludes>
<!-- Set the package of the generated code -->
<generatePackage>com.foo.something</generatePackage>
<generateDirectory>${project.build.directory}/generated-sources/xjc1/a_something</generateDirectory>
<!-- Define the directory where we should find the XSD files -->
<schemaDirectory>
src/main/resources/dtd/someplace/a/
</schemaDirectory>
<schemaIncludes>
<source>*.xsd</source>
</schemaIncludes>
</configuration>
</execution>
</executions>
<plugin>
</plugins>
And in the enums XSD
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" id="commonEnums"
targetNamespace="http://foo.com/xsd/commons/enum"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.1"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="annox">
<xs:simpleType name="bulletinCategory">
<xs:annotation>
<xs:appinfo>
<annox:annotateEnumValueMethod>#java.lang.Deprecated</annox:annotateEnumValueMethod>
</xs:appinfo>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="valueA" />
<xs:enumeration value="valueB" />
<xs:enumeration value="valueC" />
</xs:restriction>
</xs:simpleType>
</xs>
Ideally speaking the #deprecated should be #XmlJavaTypeAdapter(FooAdapter.class) but I thought let's start small.
The problem is probably that you've included customizations directly into the enums.xsd. So when you compile other schemas, these customizations are considered as well.
But since you also seem to use the enums.xsd as episode, this effectively prevents generation of enum classes. With no enum classes, customizations cannot be applied so they are not marked as "recognized" and this produces the error you get.
To solve this, when compiling enums.xsd, simply move customizations into a separate bindings file and use it during compilation.
Then, when compiling other schemas, use enums.xsd as episode but do not use that bindings file with customizations for enums.xsd.

JAXB generated classes of certain types implementing a custom interface

I am working on an application that uses XJC to generate Java POJOs from XSDs. There are dozens of schemas, and that number will grow. The application also needs to be able to handle different versions of the same schema, which means that I will have multiple schemas defining common types. I am trying to customize the bindings so that certain core types implement a common interface. The Inheritance plugin of JAXB2 Basics seems to do what I need, but I can't seem to nail the right syntax.
Here is the relevant part of my schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://example.com/core"
targetNamespace="http://example.com/core"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
...
<xs:complexType name="addressType">
<xs:sequence>
<xs:element name="Address" type="xs:string"/>
<xs:element name="City" type="xs:string"/>
<xs:element name="Province" type="xs:string"/>
<xs:element name="Country" type="xs:string"/>
<xs:element name="County" type="xs:string" minOccurs="0"/>
<xs:element name="PostalCode" type="xs:string"/>
</xs:sequence>
</xs:complexType>
...
</xs:schema>
... and this is what my custom binding file looks like:
<?xml version="1.0"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
xmlns:my="http://example.com/core"
jaxb:extensionBindingPrefixes="inheritance"
version="2.1">
<jaxb:bindings scd="x-schema::my" xmlns:my="http://example.com/core">
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
<xjc:simple/>
</jaxb:globalBindings>
<jaxb:bindings scd="/type::my:addressType">
<inheritance:implements>com.mysite.validator.ValidatableAddress</inheritance:implements>
<!--<xjc:superInterface name="com.mysite.validator.ValidatableAddress"/>-->
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
I'm using the scd approach, because in all the "traditional" binding examples that show how to use the inheritence plugin, schemaLocation is specified. I want to avoid having to specify schemaLocation because of our large (and growing) number of schemas. I don't want to have to change the binding file every time we add a new schema. So, scd seems like it will satisfy this requirement.
However when I run the build using the above binding, I get this:
[xjc] [ERROR] cvc-elt.1: Cannot find the declaration of element 'inheritance:implements'.
[xjc] line 18 of file:/dev/workspace/my_app/etc/schemas/bindings-common.xml
[xjc] failure in the XJC task. Use the Ant -verbose switch for more details
[xjc] classLoader = java.net.URLClassLoader#ebcdbb
[xjc] SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7#14562c5
If I comment out the inheritance:implements line and uncomment the xjc:superInterface line, the error goes away and the build completes successfully, but my AddressType classes don't implement the ValidatableAddress type.
Can the inheritence plugin be used with scd? Can xjc:superInterface be limited to only certain elements?
Cheers.
Author of jaxb2-basics here.
See this issue in XJC. In short, XJC for some reason does not allow custom/vendor customization elements in SCD bindings.
inheritance:implements is such customization element.
So no, this does not work due a problem in XJC.
I personally bind via schemaLocation and XPath but use a "virtual" schema location URI and rewrite it via catalogs.
SCD would have been a much better choice (you're absolutely right here) but it just does not work.
Update on virtual schema location and catalogs.
Here's an example of binding which customizes some complex type:
<jaxb:bindings
schemaLocation="http://schemas.opengis.net/wps/2.0/wpsCommon.xsd"
node="/xs:schema">
<jaxb:bindings node="xs:element[#name='Data']/xs:complexType">
<wildcard:lax/>
</jaxb:bindings>
</jaxb:bindings>
It is bound via schemaLocation and XPath. The schemaLocation is an existing URL, but in the build it is rewritten via catalog into the resource inside a Maven artifact:
REWRITE_SYSTEM "http://schemas.opengis.net" "maven:org.jvnet.ogc:ogc-schemas:jar::!/ogc"
So basically http://schemas.opengis.net/wps/2.0/wpsCommon.xsd will be loaded from the ogc-schema.jar!/ogc/wps/2.0/wpsCommon.xsd.
Using maven-jaxb2-plugin you can refer to binding files inside Maven artifacts as well:
<binding>
<dependencyResource>
<groupId>${project.groupId}</groupId>
<artifactId>ows-v_2_0</artifactId>
<resource>ows-v_2_0.jsonix.xjb</resource>
<version>${project.version}</version>
</dependencyResource>
</binding>
So, in combination, it allows writing binding files once and reuse them across modules.
But this was all a huge pain to figure out. I did it for the ogc-schemas project which is now some 50 heavily interconnected schemas. I heavily suffer from XJC drawbacks and issues, but this is the best possible at the moment. I even thought about forking and patching XJC, but this is far of effort limits I can afford.
So I've ended up with a number of mindblogging workarounds which somehow do the job at the end of the day.
Thanks to lexicore for the prompt and detailed answers. However that approach wasn't working for me, so I ended up with the following solution...
Because I am using Ant to invoke XJC, I ended up leveraging Ant's <copy filtering="true"...> capabilities to dynamically generate the binding file.
Here is my binding "template" file (bindings-common.xml):
<?xml version="1.0"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
xmlns:my="http://http://example.com/core"
jaxb:extensionBindingPrefixes="inheritance"
version="2.1">
<jaxb:bindings>
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
<xjc:simple/>
</jaxb:globalBindings>
</jaxb:bindings>
<jaxb:bindings
schemaLocation="#bindingSchema#"
node="/xs:schema">
<jaxb:bindings node="//xs:complexType[#name='addressType']">
<inheritance:implements>com.example.validator.ValidatableAddress</inheritance:implements>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Note this line:
<jaxb:bindings
schemaLocation="#bindingSchema#"
node="/xs:schema">
This variable will get populated by Ant for each of the schemas that I am processing:
<property name="jaxb.binding.template" value="../etc/form-schemas/bindings-common.xml"/>
<property name="jaxb.binding.file" value="${jaxb.src.dir}/bindings-common${schema.version}.xml"/>
<echo message="Filtering ${jaxb.binding.file} using template ${jaxb.binding.template}"/>
<copy file="${jaxb.binding.template}"
tofile="${jaxb.binding.file}"
filtering="true">
<filterset>
<filter token="bindingSchema" value="../../etc/form-schemas/${schema.version}/common.xsd"/>
</filterset>
</copy>
<xjc destdir="${jaxb.src.dir}"
extension="true"
schema="${schema.file}"
package="${package}"
binding="${jaxb.binding.file}">
<arg value="-episode"/>
<arg value="${jaxb.src.dir}/common${schema.version}.episode"/>
<arg line="-Xinheritance"/>
<!-- Plugins -->
<classpath>
<fileset dir="../build-libs/">
<!-- JAXB2 Basics library -->
<include name="jaxb2-basics-0.6.4.jar"/>
<!-- JAXB2 Basics library dependencies -->
<include name="jaxb2-basics-runtime-0.6.4.jar"/>
<include name="jaxb2-basics-tools-0.6.4.jar"/>
<include name="javaparser-1.0.8.jar"/>
<include name="commons-beanutils-*.jar"/>
<include name="commons-lang-*.jar"/>
<include name="commons-logging-*.jar"/>
</fileset>
</classpath>
</xjc>
</target>
Hopefully this will help future generations of JAXB victims.

How to generate an XML schema file from (JAXB) annotated Java classes, using JDK8

The instructions to generate schema through running "schenagen" as suggested in Java API documentation worked with JDK7, but not with JDK8.
Here is the documentation page:
http://download.java.net/jdk8/docs/technotes/guides/xml/jaxb/index.html
Here is the line from this page with links to the instructions:
"
Running the schema generator (schemagen): [command-line instructions, using the SchemaGen Ant task]
"
Schema generator does not work because some classes have been removed from JDK8:
"java.lang.ClassNotFoundException: com.sun.mirror.apt.AnnotationProcessorFactory"
There is another solution suggested here:
Generating XSD schemas from JAXB types in Maven?
This solution also works with JDK7 but not with JDK8; it will end up with a similar error:
"Class not foundcom/sun/tools/apt/Main.class"
The root cause is probably the same: the annotation processing tools are removed from JDK8.
This change was planned in JEP 117 long time ago:
http://openjdk.java.net/jeps/117
How can I generate an XML schema file from (JAXB) annotated Java classes now, using JDK8?
This was a bug in the "jaxb2-maven-plugin". You must use the version 1.6 or later of the plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<goals>
<goal>schemagen</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<includes>
<include>com/projectname/model/*.java</include>
</includes>
<outputDirectory>${project.build.directory}/schemas</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
You can use the generateSchema method on JAXBContext to generate an XML Schema:
http://docs.oracle.com/javase/7/docs/api/javax/xml/bind/JAXBContext.html#generateSchema%28javax.xml.bind.SchemaOutputResolver%29

Prefixing JAXB generated classes

I have this Maven "task" to generate Java classes from an XSD file using JAXB.
<!-- XML to Java classes -->
<plugin>
<groupId>com.sun.tools.xjc.maven2</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>nl.compay.service</generatePackage>
<schemaDirectory>src/main/webapp/compay</schemaDirectory>
</configuration>
</plugin>
For an XSD type "User", it generates a class named "User" (duh). However, I also have a JPA entity class called "User" (though in a different package).
Can I change the XML config above to let JAXB prefix the generated classes with something like "XML"?
This is a common requirement. You can do that by providing an additional JAXB binding file to customize how JAXB translates the Schema type names into Java class names.
These files normally end in extension ".xjb". You need to create one for your schema, for example:
<jxb:bindings version="1.0"
xmlns:jxb="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"
jxb:extensionBindingPrefixes="xjc">
<jxb:bindings schemaLocation="nl.company.service.xsd" node="/xs:schema">
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName prefix="XML"/>
<jxb:anonymousTypeName prefix="XML"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
After you've done that, drop the xjb file somewhere in your build directory and tell Maven to make use of it during translation:
<includeBindings>
<includeBinding>mybindings.xjb</includeBinding>
</includeBindings>
And here's a hint for the road: if you are in a path that contains spaces (e.g. "Documents and Settings\user\project") then JAXB will fall over with strange errors.

Resources