NeuroAgent

How to Fix JAXBException in Java 9: Complete Guide

Learn how to resolve java.lang.NoClassDefFoundError for JAXB in Java 9. Complete guide with command-line fixes and project configuration solutions for Maven and Gradle.

How to resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException in Java 9?

I have code that uses JAXB API classes, which were included in the JDK from Java 6 through Java 8. When I run the same code with Java 9, I encounter runtime errors indicating that JAXB classes cannot be found.

Since JAXB classes were part of the JDK since Java 6, why can Java 9 no longer locate these classes, and how can I resolve this issue?

NeuroAgent

The java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException in Java 9 occurs because JAXB (Java Architecture for XML Binding) was deprecated in Java 9 and completely removed from Java 11 and later versions as part of Java EE’s migration to the Jakarta EE project. To resolve this issue, you can either use the --add-modules java.xml.bind command line flag to explicitly include the JAXB module, or add JAXB dependencies manually to your project configuration.

Contents

Understanding the Problem: Why JAXB is Missing in Java 9

In Java 8 and earlier versions, JAXB was included as part of the standard Java Development Kit (JDK). However, with the introduction of Java 9’s module system (Project Jigsaw), Oracle began the process of removing Java EE APIs from the JDK to make it more modular.

According to the official documentation, the java.xml.bind module defines the Java Architecture for XML Binding (JAXB) API and is considered “upgradeable” but was deprecated starting from Java 9.

The key reasons for this change include:

  • Modularity: Making the JDK more modular by removing optional APIs
  • Standardization: Moving Java EE specifications to the Jakarta EE project under the Eclipse Foundation
  • Reduced footprint: Creating a smaller, more focused JDK for different use cases

This means that code that worked seamlessly in Java 8 will fail in Java 9+ because the javax.xml.bind package is no longer available in the default classpath.

Command Line Solutions

Using --add-modules Flag

The quickest way to make JAXB available to your application is to use the --add-modules command line argument when running your Java application:

bash
java --add-modules java.xml.bind -jar your-application.jar

For compilation, you can also specify this during the build process:

bash
javac --add-modules java.xml.bind YourClass.java

JVM Arguments for Gradle/Maven Projects

When building with Gradle or Maven, you can add these JVM arguments to your build configuration:

For Gradle:

gradle
applicationDefaultJvmArgs = ["--add-modules", "java.xml.bind"]

For Maven:

xml
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>--add-modules java.xml.bind</argLine>
    </configuration>
</plugin>

Important Note: As mentioned in the Baeldung article, while the --add-modules approach works quickly, it might not be the best long-term solution because it’s essentially a workaround for the module system changes.

Project Configuration Solutions

Adding JAXB Dependencies to Maven

For a more permanent solution, you can add the JAXB API and implementation dependencies to your pom.xml file:

xml
<dependencies>
    <!-- JAXB API -->
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
    
    <!-- JAXB Implementation -->
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.1</version>
    </dependency>
    
    <!-- For JDK 9+ compatibility, you might also need -->
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>javax.activation-api</artifactId>
        <version>1.2.0</version>
    </dependency>
</dependencies>

Adding JAXB Dependencies to Gradle

For Gradle projects, add these dependencies to your build.gradle file:

gradle
dependencies {
    implementation 'javax.xml.bind:jaxb-api:2.3.1'
    implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.1'
    implementation 'javax.activation:javax.activation-api:1.2.0'
}

IDE Configuration

If you’re using an IDE like IntelliJ IDEA or Eclipse, you might need to:

  1. Update your project structure to use the new dependencies
  2. Rebuild your project to ensure all dependencies are properly resolved
  3. Verify that the JAXB classes are now available in your classpath

Migration Considerations

Long-term Migration Strategy

While temporary fixes like --add-modules work, consider these long-term strategies:

  1. Jakarta EE Migration: For Java 11 and later, migrate from javax.xml.bind to jakarta.xml.bind as part of the Jakarta EE project.

  2. Alternative Libraries: Consider using modern XML processing libraries like:

    • Jackson XML module
    • XStream
    • Woodstox
  3. Dependency Management: Ensure your build tools are configured to handle the JAXB dependencies properly across different Java versions.

Java Version Compatibility

Here’s a compatibility reference:

Java Version JAXB Status Recommended Solution
Java 6-8 Included No changes needed
Java 9 Deprecated --add-modules or manual dependencies
Java 10 Deprecated --add-modules or manual dependencies
Java 11+ Removed Manual dependencies or Jakarta EE migration

Practical Implementation Examples

Basic JAXB Usage Example

Here’s a simple example demonstrating JAXB usage that would work after applying the fixes:

java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class ExampleObject {
    private String name;
    private int value;
    
    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getValue() { return value; }
    public void setValue(int value) { this.value = value; }
    
    public static void main(String[] args) {
        try {
            // This will work after applying the JAXB fixes
            JAXBContext context = JAXBContext.newInstance(ExampleObject.class);
            System.out.println("JAXBContext created successfully!");
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

Running with Java 9

To run this example with Java 9, you can use:

bash
# Option 1: Using --add-modules
java --add-modules java.xml.bind --module-path your-dependency-path -cp . ExampleObject

# Option 2: With JAR file containing JAXB dependencies
java -cp "your-app.jar:jaxb-api.jar:jaxb-runtime.jar:" ExampleObject

Maven Project Setup Example

Here’s a complete Maven project structure that resolves the JAXB issue:

xml
<?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>jaxb-java9-example</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <properties>
        <maven.compiler.source>9</maven.compiler.source>
        <maven.compiler.target>9</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.1</version>
        </dependency>
        
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>javax.activation-api</artifactId>
            <version>1.2.0</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>9</source>
                    <target>9</target>
                    <compilerArgs>
                        <arg>--add-modules</arg>
                        <arg>java.xml.bind</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Sources

  1. Stack Overflow - How to resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
  2. Baeldung - Handling NoClassDefFoundError for JAXBException in Java
  3. Mkyong.com - java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
  4. CodeJava.net - [Solved] java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
  5. GeeksforGeeks - How to Resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
  6. Mastertheboss - How to solve java.lang.NoClassDefFoundError: javax/xml/bind Classes
  7. ConcretePage - [SOLVED-JAVA 9] Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
  8. Oracle Documentation - java.xml.bind (Java SE 9 & JDK 9)
  9. LogicBig - Java 9 Modules - The Root Modules
  10. Jesper de Jong - JAXB on Java 9, 10, 11 and beyond

Conclusion

The java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException in Java 9 is a common issue caused by Oracle’s decision to remove Java EE APIs from the JDK starting with Java 9. To resolve this problem:

  1. For quick fixes: Use the --add-modules java.xml.bind command line flag when running or compiling your application
  2. For permanent solutions: Add JAXB dependencies manually to your Maven or Gradle project configuration
  3. For long-term planning: Consider migrating to Jakarta EE APIs or alternative XML processing libraries

The key takeaway is that while the change was disruptive, it’s manageable with proper dependency management and understanding of the Java module system. Always test your application with the target Java version and ensure all required dependencies are properly configured in your build system.