How can I tell jaxb / Maven to generate multiple schema packages?

Maven 2JaxbSchemaXsdJava

Maven 2 Problem Overview


Example:

</plugin>       
       <plugin>
           <groupId>org.jvnet.jaxb2.maven2</groupId>
           <artifactId>maven-jaxb2-plugin</artifactId>
           <version>0.7.1</version>
           <executions>
             <execution>
               <goals>
                 <goal>generate</goal>
               </goals>
             </execution>
           </executions>
            <configuration>
             <schemaDirectory>src/main/resources/dir1</schemaDirectory>
              <schemaIncludes>
                  <include>schema1.xsd</include>
              </schemaIncludes>
              <generatePackage>schema1.package</generatePackage>
           </configuration>
         </plugin>
          <plugin>
           <groupId>org.jvnet.jaxb2.maven2</groupId>
           <artifactId>maven-jaxb2-plugin</artifactId>
           <version>0.7.1</version>
           <executions>
             <execution>
               <goals>
                 <goal>generate</goal>
               </goals>
             </execution>
           </executions>
            <configuration>
             <schemaDirectory>src/main/resources/dir2</schemaDirectory>
              <schemaIncludes>
                  <include>schema2.xsd</include>
              </schemaIncludes>
              <generatePackage>schema2.package</generatePackage>
           </configuration>
         </plugin>
       </plugins>

What happened: Maven executes the the first plugin. Then deletes the target folder and creates the second package, which then is visible.

I tried to set target/somedir1 for the first configuration and target/somedir2 for the second configuration. But the behavior does not not change? Any ideas? I do not want to generate the packages directly in the src/main/java folder, because these packages are genereated and should not be mixed with manual created classes.

Maven 2 Solutions


Solution 1 - Maven 2

I had to specify different generateDirectory (without this, the plugin was considering that files were up to date and wasn't generating anything during the second execution). And I recommend to follow the target/generated-sources/<tool> convention for generated sources so that they will be imported in your favorite IDE automatically. I also recommend to declare several execution instead of declaring the plugin twice (and to move the configuration inside each execution element):

<plugin>
  <groupId>org.jvnet.jaxb2.maven2</groupId>
  <artifactId>maven-jaxb2-plugin</artifactId>
  <version>0.7.1</version>
  <executions>
    <execution>
      <id>schema1-generate</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <schemaDirectory>src/main/resources/dir1</schemaDirectory>
        <schemaIncludes>
          <include>shiporder.xsd</include>
        </schemaIncludes>
        <generatePackage>com.stackoverflow.package1</generatePackage>
        <generateDirectory>${project.build.directory}/generated-sources/xjc1</generateDirectory>
      </configuration>
    </execution>
    <execution>
      <id>schema2-generate</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <schemaDirectory>src/main/resources/dir2</schemaDirectory>
        <schemaIncludes>
          <include>books.xsd</include>
        </schemaIncludes>
        <generatePackage>com.stackoverflow.package2</generatePackage>
        <generateDirectory>${project.build.directory}/generated-sources/xjc2</generateDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

With this setup, I get the following result after a mvn clean compile

$ tree target/
target/
├── classes
│   ├── com
│   │   └── stackoverflow
│   │       ├── App.class
│   │       ├── package1
│   │       │   ├── ObjectFactory.class
│   │       │   ├── Shiporder.class
│   │       │   ├── Shiporder$Item.class
│   │       │   └── Shiporder$Shipto.class
│   │       └── package2
│   │           ├── BookForm.class
│   │           ├── BooksForm.class
│   │           ├── ObjectFactory.class
│   │           └── package-info.class
│   ├── dir1
│   │   └── shiporder.xsd
│   └── dir2
│       └── books.xsd
└── generated-sources
├── xjc
│   └── META-INF
│       └── sun-jaxb.episode
├── xjc1
│   └── com
│       └── stackoverflow
│           └── package1
│               ├── ObjectFactory.java
│               └── Shiporder.java
└── xjc2
└── com
└── stackoverflow
└── package2
├── BookForm.java
├── BooksForm.java
├── ObjectFactory.java
└── package-info.java

Which seems to be the expected result.

Solution 2 - Maven 2

You can use also JAXB bindings to specify different package for each schema, e.g.

<jaxb:bindings xmlns:jaxb="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" version="2.0" schemaLocation="book.xsd">

	<jaxb:globalBindings>
		<xjc:serializable uid="1" />
	</jaxb:globalBindings>

	<jaxb:schemaBindings>
		<jaxb:package name="com.stackoverflow.book" />
	</jaxb:schemaBindings>

</jaxb:bindings>

Then just use the new maven-jaxb2-plugin 0.8.0 <schemas> and <bindings> elements in the pom.xml. Or specify the top most directory in <schemaDirectory> and <bindingDirectory> and by <include> your schemas and bindings:

<schemaDirectory>src/main/resources/xsd</schemaDirectory>
<schemaIncludes>
	<include>book/*.xsd</include>
	<include>person/*.xsd</include>
</schemaIncludes>
<bindingDirectory>src/main/resources</bindingDirectory>
<bindingIncludes>
	<include>book/*.xjb</include>
	<include>person/*.xjb</include>
</bindingIncludes>

I think this is more convenient solution, because when you add a new XSD you do not need to change Maven pom.xml, just add a new XJB binding file to the same directory.

Solution 3 - Maven 2

you should change that to define the plugin only once and do twice execution areas...like the following...and the generateDirectory should be set (based on the docs)..

<plugin>
  <groupId>org.jvnet.jaxb2.maven2</groupId>
  <artifactId>maven-jaxb2-plugin</artifactId>
  <version>0.7.1</version>
  <executions>
    <execution>
      <id>firstrun</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <generateDirectory>target/gen1</generateDirectory>
        <schemaDirectory>src/main/resources/dir1</schemaDirectory>
        <schemaIncludes>
          <include>schema1.xsd</include>
        </schemaIncludes>
        <generatePackage>schema1.package</generatePackage>
      </configuration>
    </execution>
    <execution>
      <id>secondrun</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <generateDirectory>target/gen2</generateDirectory>
        <schemaDirectory>src/main/resources/dir2</schemaDirectory>
        <schemaIncludes>
          <include>schema2.xsd</include>
        </schemaIncludes>
        <generatePackage>schema2.package</generatePackage>
      </configuration>
    </execution>
  </executions>
</plugin>

It seemed to me that you are fighting against single artifact rule of maven...may be you should think about this.

Solution 4 - Maven 2

i have solved with:

                        <removeOldOutput>false</removeOldOutput>
                        <clearOutputDir>false</clearOutputDir>
                        <forceRegenerate>true</forceRegenerate>

add this to each configuration ;)

Solution 5 - Maven 2

This can also be achieved by specifying stale file name for schemas and not clearing output directory. The default out put directory is automatically included in classpath which is little convenient. If we specify different output directory one has to take care of classpath to use this code in IDE. For example -

<plugins>
		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>jaxb2-maven-plugin</artifactId>
			<version>1.3.1</version>
			<configuration>
				<quiet>true</quiet>
				<verbose>false</verbose>
				<clearOutputDir>false</clearOutputDir>
				<readOnly>true</readOnly>
				<arguments>-mark-generated</arguments>
			</configuration>
			<executions>
				<execution>
					<id>reportingSchema</id>
					<goals>
						<goal>xjc</goal>
					</goals>
					<configuration>
						<schemaDirectory>src/main/resources/schema/r17/schemaReporting</schemaDirectory>
						<schemaIncludes>
							<include>OCISchemaReporting.xsd</include>
						</schemaIncludes>
						<packageName>com.broadsoft.oci.r17.reporting</packageName>
						<staleFile>${build.directory}/generated-sources/.jaxb-staleFlag-reporting</staleFile>
					</configuration>
				</execution>
				<execution>
					<id>schemaAS</id>
					<goals>
						<goal>xjc</goal>
					</goals>
					<configuration>
						<schemaDirectory>src/main/resources/schema/r17/schemaAS</schemaDirectory>
						<schemaIncludes>
							<include>OCISchemaAS.xsd</include>
						</schemaIncludes>
						<packageName>com.broadsoft.oci.r17.as</packageName>
						<staleFile>${build.directory}/generated-sources/.jaxb-staleFlag-as</staleFile>
					</configuration>
				</execution>
			</executions>
		</plugin>
</plugins>

Source:Generating Code with JAXB Plugin

Solution 6 - Maven 2

This is fixed in version 1.6 of the plugin.

			<groupId>org.codehaus.mojo</groupId>
			<artifactId>jaxb2-maven-plugin</artifactId>
			<version>1.6</version>

Quick note though, I noticed that the first iteration output was being deleted. I fixed it by adding the following to each of the executions.

						<removeOldOutput>false</removeOldOutput>
						<clearOutputDir>false</clearOutputDir>

Here is my full working example with each iteration outputting correctly. BTW I had to do this due to a duplicate namespace problem with the xsd's I was given. This seems to resolve my problem.

		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>jaxb2-maven-plugin</artifactId>
			<version>1.6</version>
			<executions>
				<execution>
					<id>submitOrderRequest</id>
					<goals>
						<goal>xjc</goal>
					</goals>
					<configuration>
						<extension>true</extension>
						<schemaDirectory>src/main/resources/xsd/</schemaDirectory>
						<!-- <schemaFiles>getOrderStatusResponse.xsd,quoteShippingRequest.xsd,quoteShippingResponse.xsd,submitOrderRequest.xsd,submitOrderResponse.xsd</schemaFiles> -->
						<schemaFiles>submitOrderRequest.xsd</schemaFiles>
						<bindingDirectory>${project.basedir}/src/main/resources/xjb</bindingDirectory>
						<bindingFiles>submitOrderRequest.xjb</bindingFiles>
						<removeOldOutput>false</removeOldOutput>
						<clearOutputDir>false</clearOutputDir>
					</configuration>
				</execution>
				<execution>
					<id>submitOrderResponse</id>
					<goals>
						<goal>xjc</goal>
					</goals>
					<configuration>
						<extension>true</extension>
						<schemaDirectory>src/main/resources/xsd/</schemaDirectory>
						<!-- <schemaFiles>getOrderStatusResponse.xsd,quoteShippingRequest.xsd,quoteShippingResponse.xsd,submitOrderRequest.xsd,submitOrderResponse.xsd</schemaFiles> -->
						<schemaFiles>submitOrderResponse.xsd</schemaFiles>
						<bindingDirectory>${project.basedir}/src/main/resources/xjb</bindingDirectory>
						<bindingFiles>submitOrderResponse.xjb</bindingFiles>
						<removeOldOutput>false</removeOldOutput>
						<clearOutputDir>false</clearOutputDir>
					</configuration>
				</execution>
			</executions>

		</plugin>

Solution 7 - Maven 2

The following works for me, after much trial

<plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jaxb2-maven-plugin</artifactId>
         <version>2.1</version>
         <executions>
            <execution>
              <id>xjc1</id>
              <goals>
                  <goal>xjc</goal>
              </goals>
             <configuration>
                <packageName>com.mycompany.clientSummary</packageName>
               <sourceType>wsdl</sourceType>
           		<sources>
           		<source>src/main/resources/wsdl/GetClientSummary.wsdl</source>
           		</sources>
                <outputDirectory>target/generated-sources/xjb</outputDirectory>
                 <clearOutputDir>false</clearOutputDir>
           	</configuration>
          </execution>
             
          <execution>
             <id>xjc2</id>
             <goals>
                 <goal>xjc</goal>
             </goals>
             <configuration>
           		<packageName>com.mycompany.wsclient.employerProfile</packageName>
               	<sourceType>wsdl</sourceType>
           		<sources>
           		<source>src/main/resources/wsdl/GetEmployerProfile.wsdl</source>
           		</sources>
                <outputDirectory>target/generated-sources/xjb</outputDirectory>
                <clearOutputDir>false</clearOutputDir>
      	 </configuration>
         </execution>
             
         <execution>
            <id>xjc3</id>
            <goals>
                <goal>xjc</goal>
            </goals>
            <configuration>
          		<packageName>com.mycompany.wsclient.producersLicenseData</packageName>
          		<sourceType>wsdl</sourceType>
           		<sources>
           		<source>src/main/resources/wsdl/GetProducersLicenseData.wsdl</source>
           		</sources>
                <outputDirectory>target/generated-sources/xjb</outputDirectory>
              	<clearOutputDir>false</clearOutputDir>
    	 	</configuration>
        </execution>
             
        
     </executions>
  </plugin>

Solution 8 - Maven 2

I encountered a lot of problems when using jaxb in Maven but i managed to solve your problem by doing the following

First create a schema.xjc file

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               jaxb:version="2.0">
    <jaxb:bindings schemaLocation="YOUR_URL?wsdl#types?schema1">
        <jaxb:schemaBindings>
            <jaxb:package name="your.package.name.schema1"/>
        </jaxb:schemaBindings>
    </jaxb:bindings>
    <jaxb:bindings schemaLocation="YOUR_URL??wsdl#types?schema2">
        <jaxb:schemaBindings>
            <jaxb:package name="your.package.name.schema2"/>
        </jaxb:schemaBindings>
    </jaxb:bindings>
</jaxb:bindings>

The package name can be anything you want it to be, as long as it doesn't contain any reserved keywords in Java

Next you have to create the wsimport.bat script to generate your packaged and code at the preferred location.

cd C:\YOUR\PATH\TO\PLACE\THE\PACKAGES
wsimport -keep -verbose -b "C:\YOUR\PATH\TO\schema.xjb" YOUR_URL?wsdl
pause

If you do not want to use cd, you can put the wsimport.bat in "C:\YOUR\PATH\TO\PLACE\THE\PACKAGES"

If you run it without -keep -verbose it will only generate the packages but not the .java files.

The -b will make sure the schema.xjc is used when generating

Solution 9 - Maven 2

There is another, a clear one (IMO) solution to this There is a parameter called "staleFile" that uses as a flag to not generate stuff again. Simply alter it in each execution.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionM.R.View Question on Stackoverflow
Solution 1 - Maven 2Pascal ThiventView Answer on Stackoverflow
Solution 2 - Maven 2xmedekoView Answer on Stackoverflow
Solution 3 - Maven 2khmarbaiseView Answer on Stackoverflow
Solution 4 - Maven 2Davide ConsonniView Answer on Stackoverflow
Solution 5 - Maven 2Prashant C ChaturvediView Answer on Stackoverflow
Solution 6 - Maven 2Chris HinshawView Answer on Stackoverflow
Solution 7 - Maven 2Brian teggartView Answer on Stackoverflow
Solution 8 - Maven 2Glenn Van SchilView Answer on Stackoverflow
Solution 9 - Maven 2eugen-friedView Answer on Stackoverflow