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

120,634

Solution 1

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

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

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

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 5

i have solved with:

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

add this to each configuration ;)

Share:
120,634
M.R.
Author by

M.R.

Updated on March 08, 2020

Comments

  • M.R.
    M.R. about 4 years

    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.

  • Devanshu Mevada
    Devanshu Mevada almost 14 years
    The one artifact per module rule is true but... the OP is not generating two artifacts.
  • Newtopian
    Newtopian almost 14 years
    thanks, I actually had the same problem yesterday but momentarily gave op on it. Your solution works almost perfectly, my only issue now is that I cannot get Eclipse to compile without error. All is good on the command line though. My current workaround is that I declare these folders in target as source folders and all is good.. though I'm not certain I like it much, I'd rather create a jar with the generated code and just use it directly
  • M.R.
    M.R. almost 14 years
    The eclipse plugin m2eclipse does update the build path. After generating the beans with mvc clean assembly:assembly I just run [right click on project] > [Maven] > [Update Project Configuration] and it updates the build path.
  • Devanshu Mevada
    Devanshu Mevada almost 14 years
    @Newtopian See @M.R.'s comment, m2eclipse will do that for you if you follow the convention I mentioned.
  • Newtopian
    Newtopian almost 14 years
    hmm ok then, turns out to do the same thing I did manually, only now it takes just one or two clicks. Still strange to see target in the source folders but now it's almost free to do so I'll keep it :-)
  • Admin
    Admin over 12 years
    You could also add it only to the <executions> tag. That's sufficient. <removeOldOutput> is set to false by default. But I can't find <clearOutputDir> at static.highsource.org/mjiip/maven-jaxb2-plugin/…
  • santiagozky
    santiagozky about 12 years
    what if the schemaDirectory is the same for all? I have many xsd's and wsdl that should be mapped to different packages. in my case all the packages end up having all the classes (all classes in all packages)
  • Kev
    Kev over 11 years
    Whilst trivial the edit to provide a syntax highlight hint does improve the legibility of the post
  • xmedeko
    xmedeko over 11 years
    OK, thanks for the explanation. I have not get that the edit added syntax highlighting.
  • Rakesh
    Rakesh about 11 years
    Had to add staleFile for both the configurations <staleFile>${project.build.directory}/jaxb2/.xjcStaleFlag_1<‌​/staleFile>
  • Ben Thurley
    Ben Thurley over 10 years
    This is the best answer for me as I wouldn't want to keep changing the pom each time a new schema is added.
  • dario nascimento
    dario nascimento almost 9 years
    Any way to have a single "execution" tag for all files instead of specifying one "execution" per schema?
  • MilacH
    MilacH almost 7 years
    For me the real solution, cause you can generate everythong in same folder
  • Denis Stephanov
    Denis Stephanov over 6 years
    I know it is old question but I hope something answer me. I use that code and it works. But when I want set up same same package it always generate only one schema. For example in first execution I set com.myproject.answer and in second execution com.myproject.request .. and after source generating I have only *answer package and request is missing ... any idea how to fix it? Generate directory I set also same.
  • MattWeiler
    MattWeiler about 5 years
    Thank you, I had this same issue and this worked perfectly for me :)
  • TurnipEntropy
    TurnipEntropy almost 4 years
    The one issue here is if book and person are in the same target namespace in the xsd. Let's say instead they had book, journal, newspaper, etc. all of which included publishable.xsd. They'd have to be in the same namespace as publishable, and thus each other, and now this breaks because you can only have one schemaBindings per namespace. I agree it's ideal, and I wish it worked for the example above, but JAXB just isn't flexible enough.
  • Ruwanka Madhushan
    Ruwanka Madhushan almost 4 years
    <clearOutputDir>false</clearOutputDir> was enough for me in my case.
  • MrSmith42
    MrSmith42 over 3 years
    Sadly this does not work when I use the same `generateDirectoryor more than one block.