The xjc
executable is not present in the JDK as of version 11. However, the functionality of xjc
is still available (right down to the command line arguments to that original executable) via external artifacts like org.glassfish.jaxb:jaxb-xjc.
xjc-maven-plugin sets up the classpath dependencies and passes the arguments you provide directly through to the XJCFacade.main
method.
The development of this plugin was motivated by problems with the jaxb2-maven-plugin with Java 9+. My company's codebase used jaxb2-maven-plugin in ~10 locations (always the xjc
goal) and we wanted to move to OpenJDK 11+ given the EOL (unpaid) for Oracle Java 8 in January 2019.
Status: deployed to Maven Central
- Supports Java 8, 9, 10, 11+, generates code from DTD or XSD
- detects the
-d
destination directoy and auto-creates directory if does not exist - sets system properties
- unit tested on Oracle JDK 8, 9, 10, 11 and OpenJDK 10, 11 (using Travis)
It is possible to use exec-maven-plugin to call xjc
via the java
goal or exec
goal to call XJCFacade.main
. There are problems though:
- With
exec:java
you can callXJCFacade.main
having setup the classpath with thejaxb-xjc
dependency butXJCFacade.main
callsSystem.exit
so that after generating your classes the maven build is killed. Obviously terrible when you want stuff to happen after generating the classes! - With
exec:exec
you can callXJCFacade.main
forked so that theSystem.exit
doesn't kill the build but you have to build the classpath yourself (16 dependencies without maven to help you). - With both of the
exec
options you need to add a call toantrun-maven-plugin
to create the destination directory if it doesn't exist.
Instead of these poor options, use xjc-maven-plugin!
mvn clean install
Here's an example where we generate java classes with package dummy
from an XSD file (pretty much a copy and paste from the unit test project):
<properties>
<jaxb.generated>${project.build.directory}/generated-sources/jaxb</jaxb.generated>
</properties>
...
<plugin>
<groupId>com.github.davidmoten</groupId>
<artifactId>xjc-maven-plugin</artifactId>
<version>VERSION_HERE</version>
<executions>
<execution>
<id>gen</id>
<!-- generate sources from the java.util.logging DTD -->
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<systemProperties>
<enableExternalEntityProcessing>true</enableExternalEntityProcessing>
</systemProperties>
<execution>
<id>gen-from-xsd-kml</id>
<!-- generate sources from the kml 2.2 xsd -->
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<systemProperties>
<enableExternalEntityProcessing>true</enableExternalEntityProcessing>
</systemProperties>
<arguments>
<!-- These are the arguments you would normally
have used with a call to xjc -->
<argument>-verbose</argument>
<!-- set the directory to hold generated classees -->
<argument>-d</argument>
<argument>${jaxb.generated}</argument>
<! -- set the directory containing schemas to convert to classes -->
<argument>${project.basedir}/src/main/jaxb/kml-2-2/xsd</argument>
<!-- set the directory containing jaxb bindings (customizations) -->
<argument>-b</argument>
<argument>${project.basedir}/src/main/jaxb/kml-2-2/bindings</argument>
</arguments>
</configuration>
</execution>
</configuration>
</execution>
</executions>
</plugin>
<!-- ensure the generated sources are on the classpath (and in built jar) -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${jaxb.generated}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Here's sample output from the plugin:
[INFO] --- xjc-maven-plugin:0.1.3-SNAPSHOT:xjc (gen-from-dtd) @ xjc-maven-plugin-test ---
[INFO] Starting xjc mojo
[INFO] destination directory (-d option) specified and does not exist, creating: /home/dxm/Development/ide/eclipse/workspace-4.7/xjc-maven-plugin/xjc-maven-plugin-test/target/generated-sources/jaxb
[INFO] setting up classpath for jaxb-xjc version 2.4.0-b180830.0438
parsing a schema...
compiling a schema...
[INFO] generating code
unknown location
dummy/Exception.java
dummy/Frame.java
dummy/Log.java
dummy/ObjectFactory.java
dummy/Param.java
dummy/Record.java
[INFO] xjc mojo finished
Note that the unknown location
line is associated with the [INFO] generating code
line and can be ignored (it's supposed to report where in the input files an error is coming from but this INFO-level log line is not associated with a real problem so no location is included).
If you want more detail including all classpath items for the xjc
call then call:
mvn clean install -X
See the Java 8 xjc documentation for descriptions of the arguments to pass to xjc using the plugin.
For project maintainers, to use a new version of jaxb-xjc just update the glassfish.jaxb.version
in the root pom.xml.