Is there a way to generate value constructors when creating Java code using jakarta dependencies in JAXB?

1k views Asked by At

I'm migrating my JAXB code from the javax.* to the jakarta.* dependencies. Until now I used the following maven plugin to generate the Java code.

<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb23-plugin</artifactId>
<version>0.15.2</version>
<executions>
    <execution>
        ...
        <configuration>
            ...
            <args>
                <arg>-Xvalue-constructor</arg>
            </args>
        </configuration>
    </execution>
</executions>
<dependencies>
    <dependency>
        <groupId>org.jvnet.jaxb2_commons</groupId>
        <artifactId>jaxb2-value-constructor</artifactId>
        <version>3.0</version>
    </dependency>
</dependencies>
</plugin>

Of course this maven plugin creates code using the javax dependencies.

There is a fork that has been updated to jakarta:

<groupId>com.helger.maven</groupId>
<artifactId>jaxb40-maven-plugin</artifactId>

But I haven't found an updated version of the plugin which generates the value constructors (jaxb2-value-constructor).

Is there another way to generate Java code from an XSD file so that the generated code uses the new Jakarta dependencies AND comprises a simple default constructor and a value constructor (a constructor that accepts all class fields as parameter)?

3

There are 3 answers

0
xerx593 On BEST ANSWER

Not sure about (the future of) org.jvnet.jaxb2.maven2, but the actual xjc-plugin/fuctionality (jaxb2-value-constructor) seems jaxb-version-agnostic.

I could manage with (latest jakarta.xml and):

Apache's cxf-xjc-plugin

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>xjc-demo-shiporder</artifactId>
  <version>1.0-SNAPSHOT</version>
  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-xjc-plugin</artifactId>
        <version>4.0.0</version> <!-- resp. latest -->
        <executions>
          <execution>
            <id>cxf-xjc</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>xsdtojava</goal>
            </goals>
            <configuration>
              <sourceRoot>${basedir}/target/generated-sources/jaxb</sourceRoot>
              <extensions>
                <extension>org.jvnet.jaxb2_commons:jaxb2-value-constructor:3.0</extension>
              </extensions>
              <xsdOptions>
                <xsdOption>
                  <xsd>/src/main/xsd/shiporder.xsd</xsd>
                  <packagename>com.example.cxf.shiporder</packagename>
                  <extensionArgs>
                    <extensionArg>-Xvalue-constructor</extensionArg>
                  </extensionArgs>
                </xsdOption>
              </xsdOptions>
            </configuration>
          </execution>
        </executions>
      </plugin>      
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>jakarta.xml.bind</groupId>
      <artifactId>jakarta.xml.bind-api</artifactId>
      <version>4.0.0</version>
    </dependency>
  </dependencies>
</project>

...basically the quickstart, with the only "extensions": <extensions/> + <extensionsArgs>.

... but also with:

CodeMojohaus' jaxb2-maven-plugin

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jaxb2-maven-plugin</artifactId>
        <version>3.1.0</version> <!-- resp. latest -->
        <executions>
          <execution>
            <id>codehaus-xjc</id>
            <goals>
              <goal>xjc</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <arguments>
            <argument>-Xvalue-constructor</argument>
          </arguments>
          <packageName>com.example.codehaus.shiporder</packageName> 
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.jvnet.jaxb2_commons</groupId>
            <artifactId>jaxb2-value-constructor</artifactId>
            <version>3.0</version> <!-- final/archived -->
          </dependency>          
        </dependencies>
    </plugin>

..with the same "pom skeletton".

Now we have "xsd2java" generation with:

  • latest xml api and
  • "no+all-args-constructors" in the generated classes.

I would not recommend to mix both plugins in one project.

The generated sources are identical (disregarding packages and timestamps), since generated by the same (jdk) tool with equivalent input.

(xsd used: https://gist.github.com/xerx593/76e449c599307a48a5264aa746651ec8)

0
Rick O'Sullivan On

Yes, there is a way to generate Java code from an XSD file so that the generated code uses the new Jakarta dependencies AND comprises a simple default constructor and a value constructor (a constructor that accepts all class fields as parameter).

Version 2.1.1 of the hisrc-higherjaxb-maven-plugin generates Jakarta JAXB classes from an XSD file and uses hisrc-basicjaxb-plugins to extend XJC with a valueConstructor add-on.

Sample POM configuration

...
<!-- mvn hisrc-higherjaxb:help -Ddetail=true -->
<!-- mvn hisrc-higherjaxb:generate -->
<plugin>
    <groupId>org.patrodyne.jvnet</groupId>
    <artifactId>hisrc-higherjaxb-maven-plugin</artifactId>
    <version>2.1.1</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <extension>true</extension>
        <debug>true</debug>
        <args>
            <arg>-XvalueConstructor</arg>
        </args>
        <plugins>
            <plugin>
                <groupId>org.patrodyne.jvnet</groupId>
                <artifactId>hisrc-basicjaxb-plugins</artifactId>
                <version>2.1.1</version>
            </plugin>
        </plugins>
    </configuration>
</plugin>
...
0
Laurent Schoelens On

I know the question is quite old now but I wanted to notice that the plugin you used is now capable of generating Java code regarding latest JAXB API version (jakarta namespace starting with v3)

We did some refactoring so please read the migration guide if needed.

That would lead to the following configuration :

<plugin>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-maven-plugin</artifactId>
<version>4.0.0</version>
<executions>
    <execution>
        ...
        <configuration>
            ...
            <args>
                <arg>-Xvalue-constructor</arg>
            </args>
        </configuration>
    </execution>
</executions>
<dependencies>
    <dependency>
        <groupId>org.jvnet.jaxb</groupId>
        <artifactId>jaxb-plugins</artifactId>
        <version>4.0.0</version>
    </dependency>
</dependencies>
</plugin>

Note : we did integrate in former jaxb2-basics extension (now artifact is named org.jvnet.jaxb:jaxb-plugins) the 5 plugins outside of basics which you could find here, including the jaxb2-value-constructor.