how to create common xsd generated java classes - xsd

I want to generate java classes through XSDs, I want to use/include one XSD file in another but when I include them in another XSDs same java class is generated in both the packages. I am also using maven-jaxb2-plugin plugin

Do separate - aka modular - schema compilation using so-called episodes. That is to say, if you want to import schema A into schema B and generate classes for schema B, you first create a separate Maven project in order to compile schema A to a separate Maven artifact with maven-jaxb2-plugin as usual. (This is assuming the schema A stands alone, i.e. does not import any other schema; else you have to repeat the same process on the imported schema(s).) As a result, you get A.jar with the generated classes only from schema A, and most importantly, a META-INF/sun-jaxb.episode file. This file provides information about the existing XSD-to-Java bindings, and this will tell the maven-jaxb2-plugin (in fact the xjc tool underlying maven-jaxb2-plugin) what has already been generated from the schema, and therefore prevent it to re-generate the same classes again.
Then you create another Maven project in order to compile schema B, with maven artifact of A.jar among its Maven dependencies. This time, in the configuration of maven-jaxb2-plugin, you set the configuration parameter useDependenciesAsEpisodes to true. This will tell the plugin to use the .episode files from all dependencies (when there is any). You can find a basic example on the plugin's GitHub wiki. Below is a real-life example from AuthzForce project, an XACML implementation, where the OASIS XACML standard schema (xacml-core-v3-schema-wd-17.xsd) imports the W3C standard XML namespace schema (xml.xsd). Therefore, you have one Maven project/artifact for the xml.xsd, and another one for the XACML schema, where the relevant parts of the POM look like this:
<project ...>
...
<dependencies>
...
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${artifactId.prefix}-xmlns-model</artifactId>
<version>${project.parent.version}</version>
</dependency>
...
</dependencies>
<build>
<plugins>
...
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<verbose>true</verbose>
<extension>true</extension>
<strict>false</strict>
<useDependenciesAsEpisodes>true</useDependenciesAsEpisodes>
...
<catalog>src/main/jaxb/catalog.xml</catalog>
<schemaDirectory>src/main/resources</schemaDirectory>
<schemaIncludes>
<include>xacml-core-v3-schema-wd-17.xsd</include>
</schemaIncludes>
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
You notice that there is also a catalog parameter pointing to the XML catalog file. This is also important because this catalog will enable the plugin to locate the A.xsd file (xml.xsd in my example) directly in its maven artifact, so that you don't need to duplicate the file in project B or elsewhere. In my example, since the XACML schema imports xml.xsd as follows:
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
... the catalog.xml must look like this:
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="http://www.w3.org/2001/xml.xsd" uri="maven:org.ow2.authzforce:authzforce-ce-xmlns-model:jar!/xml.xsd" />
</catalog>
You notice that the uri parameter references the xml.xsd from its Maven artifact. For more info on this syntax to refer to Maven artifact resources, refer to the maven-jaxb2-plugin's wiki.
In general, to allow maximum flexibility and simplicity in managing schema locations, I recommend to specify only the namespace in schema imports. (No schemaLocation.) For example, prefer this:
<xs:import namespace="http://www.w3.org/XML/1998/namespace" />
... in which case the catalog.xml should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<public publicId="http://www.w3.org/XML/1998/namespace" uri="maven:org.ow2.authzforce:authzforce-ce-xmlns-model:jar!/xml.xsd" />
</catalog>
(This is not the case in my example exceptionally, because the official XACML schema from the standard committee uses a schemaLocation, so it's preferable to keep it as is like the original.)

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.

Manipulate JAXB to create IDREF Elements instead of JaxBElement<?>

I want to generate classes using maven-jaxb2-plugin.
My input xsd looks like the following:
<complexType>
<complexContent>
<restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
<sequence>
<element name="ReferencedElementA" type="{http://www.w3.org/2001/XMLSchema}IDREFS" minOccurs="0" />
<element name="ReferencedElementB" type="{http://www.w3.org/2001/XMLSchema}IDREF"
maxOccurs="unbounded" minOccurs="0" />
</sequence>
</restriction>
</complexContent>
Please note, that i can't alter the schema as it is provided by an external customer!
This is the generated code:
#XmlList
#XmlElement(name = "ReferencedElementA")
#XmlIDREF
#XmlSchemaType(name = "IDREFS")
protected List<Object> referencedElementA;
#XmlElementRef(name = "ReferencedElementB", namespace = "ABC", type = JAXBElement.class, required = false)
protected List<JAXBElement<Object>> referencedElementB;
As you see, the "ReferencedElementB" is generated as a List> with the #XMLElementRef-Annotation.
What i want, is something like the following:
#XmlElement(name = "ReferencedElementB")
#XmlIDREF
#XmlSchemaType(name = "IDREF")
protected List<Object> referencedElementB;
Using the workaround from Blaise Doughan, i expanded my binding file with the following code:
<bindings node = ".//xs:element[#name='ReferencedElementB']">
<class ref="java.lang.Object"/>
</bindings>
This almost finished the job, generating code like this:
#XmlElement(name = "ReferencedElementB")
#XmlSchemaType(name = "IDREF")
protected List<Object> referencedElementB;
However, the #XmlIDREF-Annotation is still missing. This produces errors during marshalling.
I've tried to inject the missing annotation via annox-plugin:
<bindings node = ".//xs:element[#name='ReferencedElementB']">
<class ref="java.lang.Object"/>
<annox:annotate target="field">#javax.xml.bind.annotation.XmlIDREF</annox:annotate>
</bindings>
But the generation fails with
compiler was unable to honor this annox:annotate customization. It is attached to a wrong place, or its inconsistent with other bindings
Once again, i'm not able to alter the input xsd.
Thank you in advance!
Please note, that i can't alter the schema as it is provided by an external customer!
I read this all the time here on SO and I always wonder - why? Why can't you alter the schema?
Well, of course you can alter the schema prior to compilation. Take the original schema and apply a patch/XSLT/whatever to modify it. As long as the result structurally matches the original schema, it is fine.
Consider your case: you use tricks and workarounds to effectively hack the generated code. How much better is it compared to modifying the schema prior to compilation? I don't think it is better at all. It is more complicated, error-prone and at the end you cannot say that your generated code is the reflection of your schema. Effectively, you do not have a schema for your code. You can't even say if your hacked generated code is an adequate reflection of the original schema.
Modifying the schema prior to compilation is quite easy. You can easily compare original vs. modified and see if changes are compatible or not. Generation is straightforward, no need for hacks and workarounds.
Now to your question.
The binding
<annox:annotate target="field">#javax.xml.bind.annotation.XmlIDREF</annox:annotate>
looks fine for me. For some reason it is not considered during schema compilation, this is why you get the error.
Hard to say why it is not considered. I'd try the following:
Check that you actually include/turn on the JAXB2 Basics Annotate plugin in your compilation:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<extension>true</extension>
<args>
<arg>-Xannotate</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
</plugin>
</plugins>
</configuration>
</plugin>
Put the customization element in its own bindings element. Maybe it does not work together with class for some reason.
I don't see more at the moment should work.
If it does not help, please send me a PR with a minimal reproducing project here:
https://github.com/highsource/jaxb2-annotate-plugin-support
under i/idrefs. I will take a look.
Disclaimer: I am the author of annox, jaxb2-annotate-plugin and maven-jaxb2-plugin.

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

How do I generate QFoo classes for the typesafe query system in DataNucleus JDO implementation?

I've created a maven module called Domain. In this module, I have all of my entity classes for my database written in Groovy. Up until this current problem, this configuration has been working quite well.
As per the directions on the DataNucleus page, I have setup my maven pom as shown below. My entity classes enhance just fine and I can use them for all of the normal old-fashioned Query APIs. However, I don't have QProduct style code-generated classes like the documentation claims will be created for me. Does anyone know what I have to do to get these classes generated?
Edit: I forgot to mention that I only have the 1.6 jdk installed on the box and I have the necessary bits set on Maven for a 1.6 source and target.
<dependencies>
<!-- JDO Dependencies -->
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
<version>[2.9, )</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-api-jdo</artifactId>
<version>[2.9, )</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-jdo-query</artifactId>
<version>[2.9, )</version>
</dependency>
<dependency>
<groupId>javax.jdo</groupId>
<artifactId>jdo-api</artifactId>
<version>[3.0, 4.0)</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/groovy</sourceDirectory>
<plugins>
<!-- This plugin does compile time enhancement of the entity classes using
bytecode weaving -->
<plugin>
<groupId>org.datanucleus</groupId>
<artifactId>maven-datanucleus-plugin</artifactId>
<version>3.0.0-release</version>
<configuration>
<metadataIncludes>**/entities/*.class</metadataIncludes>
<generateConstructor>true</generateConstructor>
<enhancerName>ASM</enhancerName>
<quiet>true</quiet>
<verbose>false</verbose>
</configuration>
<executions>
<execution>
<id>enhance-classes</id>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Use JDK1.6+, since that will invoke any annotation processors found in the CLASSPATH. Works for everyone else. Nothing to do with "maven-datanucleus-plugin". The "Q" classes are simply part of the compilation step (or better "pre-compilation")

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