2

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 Answers3

3

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)

xerx593
  • 12,237
  • 5
  • 33
  • 64
0

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>
...
Rick O'Sullivan
  • 351
  • 3
  • 7
-1

In Java, when using Jakarta XML Binding (JAXB) to generate code from an XML schema, you can generate value constructors by following these steps:

Define your XML schema: Create an XML schema file (XSD) that describes the structure and elements of your XML document.

Generate Java classes using JAXB: Use a JAXB tool, such as the xjc command-line tool or Maven plugins like jaxb2-maven-plugin, to generate Java classes from the XML schema. Ensure that you have the necessary JAXB dependencies in your project.

Customize JAXB bindings: To enable value constructors in the generated Java classes, you need to customize the JAXB bindings. This is typically done by creating a separate binding file, usually named bindings.xml.

Customize bindings.xml: Open the bindings.xml file and add the necessary customization elements to enable value constructors. Here's an example of how you can configure a value constructor:

    <jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    jaxb:extensionBindingPrefixes="xjc">

    <jaxb:bindings schemaLocation="your_schema.xsd" node="/xsd:schema">
        <jaxb:bindings node="xsd:complexType[@name='YourType']">
            <jaxb:constructor>
                <xjc:arg />
                <xjc:arg />
                <!-- Add more <xjc:arg /> elements for additional constructor arguments -->
            </jaxb:constructor>
        </jaxb:bindings>
    </jaxb:bindings>

</jaxb:bindings>

In the above example, replace your_schema.xsd with the actual path or location of your XML schema, and YourType with the name of the complex type for which you want to generate a value constructor. The <xjc:arg /> elements define the arguments of the value constructor.

Generate code with customized bindings: Run the JAXB generation tool (e.g., xjc command-line tool or Maven plugin) with the customized bindings.xml file as a parameter to generate the Java classes. The generated Java classes will now include a value constructor based on the customizations made in the bindings.xml file.

Note: The specific steps and syntax may vary depending on the version of JAXB and the tool you are using. Make sure to refer to the documentation corresponding to the version of JAXB you are using to ensure the correct configuration and customization of value constructors.

  • 1
    This answer looks like it was generated by an AI (like ChatGPT), not by an actual human being. You should be aware that [posting AI-generated output is officially **BANNED** on Stack Overflow](https://meta.stackoverflow.com/q/421831). If this answer was indeed generated by an AI, then I strongly suggest you delete it before you get yourself into even bigger trouble: **WE TAKE PLAGIARISM SERIOUSLY HERE.** Please read: [Why posting GPT and ChatGPT generated answers is not currently allowed](https://stackoverflow.com/help/gpt-policy). – tchrist Jul 09 '23 at 15:25