How can I generate classes from external XSD file using JAXB XJC
I have two projects:
a /src/main/resources/schema.xsd pom.xml
In / src / main / gene pom.xml
I want project B to generate classes from XSD that exists in Project
In the pom.xml of project B, I have:
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>src/main/resources</schemaDirectory>
<outputDirectory>src/main/gen</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
But the xsd file was not found in the classpath:
Failed to execute target org.codehaus.mojo: jaxb2-maven-plugin: 1.5: xjc (xjc) in project B: No schemas found
How can I use xsd from another project?
source to share
The problem with this configuration is what the name / path is <schemaDirectory>
expecting File
. The point File
is that it looks for files in the file system, looking from the current working directory. In this case, the root of the project. But the resource from project A is not in src/main/resources
project B. It is the classpath resource from which (when built in maven) src/main/resources
no longer exists.
I've never tried using the jaxb2-maven-plugin , so I'm not sure if this is possible.
But with maven-jaxb2-plugin it allows Compiling schema from Maven artifact . You could something like
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.9.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemas>
<schema>
<dependencyResource>
<groupId>projecta.groupid</groupId>
<artifactId>project-a</artifactId>
<version>${project.version}</version>
<resource>/schema.xsd</resource>
</dependencyResource>
</schema>
</schemas>
<generateDirectory>src/main/gen/</generateDirectory>
<generatePackage>mypackage</generatePackage>
</configuration>
</plugin>
In this case the resource (schema.xsd) is in src/main/resources
project A. The plugin generates class files in a package mypackage
and sendssrc/main/gen
source to share
My maven-jaxb2-plugin
supports separate compilation of the schema .
How to do it:
- Add your artifact
a
as an episode. - If
a.xsd
imported intob.xsd
, you must make this schema available to JAXB at compile timeb
:- One way to do this is to extract
a.xsd
from the artifacta
using the Maven dependency plugin for example. - Another way would be to use a catalog file to rewrite the location
a.xsd
into an artifacta
- One way to do this is to extract
See this test project .
The project a
is completely invisible. It just compiles the schema a.xsd
.
The project is more interesting b
. Let's get a look.
pom.xml
:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<catalog>src/main/resources/catalog.cat</catalog>
<episodes>
<episode>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin-tests-MAVEN_JAXB2_PLUGIN-82-a</artifactId>
</episode>
</episodes>
</configuration>
</plugin>
The configuration uses the artifact a
as an episode. So when JAXB / XJC comes across classes compiled to a
, it will reuse them instead of generating new ones.
By the way, you can use useDependenciesAsEpisodes
instead of setting individual episodes. In this case, all dependencies will be treated as episodes, which are very handy (less configuration).
The config also says that the directory file is :
REWRITE_SYSTEM "http://www.ab.org" "maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-MAVEN_JAXB2_PLUGIN-82-a:jar::!"
This instructs JAXB / XJC to rewrite all schema urls from http://www.ab.org
to start with maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-MAVEN_JAXB2_PLUGIN-82-a:jar::!
. The latter will be processed maven-jaxb2-plugin
and finally the resource in the a
.
Let's go closer. Driving import statement :b.xsd
http://www.ab.org/a.xsd
<import namespace="urn:a" schemaLocation="http://www.ab.org/a.xsd"/>
This will be rewritten to maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-MAVEN_JAXB2_PLUGIN-82-a:jar::!/a.xsd
be allowed a.xsd
inside the project JAR a
. So finally JAXB / XJC will be able to read this schema from the a
JAR artifact .
You can also use PUBLIC
instead REWRITE_SYSTEM
to refer a.xsd
to the namespace URI instead of the schema location (which is logically better):
PUBLIC "urn:a" "maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-MAVEN_JAXB2_PLUGIN-82-a:jar::!/a.xsd"
However there is a bug in JAXB / XJC this doesn't work if you have schemaLocation
a xs:import
.
This will work for the moment:
<xsd:import namespace="urn:a"/>
This won't work at the moment:
<xsd:import namespace="urn:a" schemaLocation="a.xsd"/>
I have submitted an Oracle pull request that fixes this, but it is not being applied yet.
The explanation above applies to maven-jaxb2-plugin
and works in versions 0.10.0 and higher.
Your original question is jaxb2-maven-plugin
from Codehaus, which is another Maven plugin. This plugin does not have all the features described above, but at least episodes should work through arguments . Directories should work as well, but I believe jaxb2-maven-plugin
doesn't support schema resolution in Maven artifacts. You can use maven-dependency-plugin
to extract a.xsd
from artifact a
.
SO Disclaimer: I am the author maven-jaxb2-plugin
.
Note to reviewers: it is not my intention here to push / advertise my plugin, I just want to provide a solution to the question asked. And it looks like my project offers the best / most elegant and complete solution.
source to share
We can also use as below in pom.xml file
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>id1</id>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<outputDirectory>src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
<packageName>com.subu.xsd.model</packageName>
<schemaDirectory>src/main/java/schemadir</schemaDirectory>
<schemaFiles>XYZ.xsd</schemaFiles>
</configuration>
</execution>
</executions>
</plugin>
source to share