Spring Boot
Java 9
ClassNotFoundException
JAXBException
Java Migration

ClassNotFoundException for javax.xml.bind.JAXBException with Spring Boot when switch to Java 9

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

This error appears when a Spring Boot application moves to Java 9 or later and still assumes JAXB classes are part of the JDK by default. Older code often imports javax.xml.bind.JAXBException successfully on Java 8, then fails at runtime after the JDK modularization changes introduced in Java 9.

Why the Error Happens

Before Java 9, JAXB APIs were bundled in the JDK in a way many applications consumed implicitly. Starting with Java 9, JAXB moved into the java.xml.bind module, and from Java 11 onward it is no longer included in the JDK as a standard bundled module.

That means there are really two migration cases:

  • On Java 9 or Java 10, the code may compile or run only if the relevant module is added explicitly.
  • On Java 11 and later, you usually need JAXB dependencies on the classpath because the JDK no longer provides them.

Spring Boot applications often surface the problem through XML marshalling libraries, SOAP clients, or older framework integrations.

The Long-Term Fix: Add JAXB Dependencies

The most reliable fix is to declare JAXB explicitly instead of depending on the JDK layout.

For Maven:

xml
1<dependencies>
2    <dependency>
3        <groupId>javax.xml.bind</groupId>
4        <artifactId>jaxb-api</artifactId>
5        <version>2.3.1</version>
6    </dependency>
7    <dependency>
8        <groupId>org.glassfish.jaxb</groupId>
9        <artifactId>jaxb-runtime</artifactId>
10        <version>2.3.8</version>
11    </dependency>
12</dependencies>

For Gradle:

gradle
1dependencies {
2    implementation "javax.xml.bind:jaxb-api:2.3.1"
3    runtimeOnly "org.glassfish.jaxb:jaxb-runtime:2.3.8"
4}

This works better than relying on JDK-specific startup flags because it keeps the application self-contained across Java versions.

Java 9 and 10 Transitional Option

If you are temporarily on Java 9 or Java 10 and need a short-term bridge, you can add the JAXB module at runtime:

bash
java --add-modules java.xml.bind -jar app.jar

That can unblock a migration, but it is not the best long-term answer. Once the application moves to Java 11 or later, explicit dependencies are the more portable fix.

Spring Boot Context

With Spring Boot, the runtime classpath is usually driven by Maven or Gradle. So the real question is not "how do I convince Java to find JAXB" but "which dependency should own JAXB in this application."

If a third-party library expects javax.xml.bind classes, adding the API alone may not be enough. You typically need both:

  • The JAXB API.
  • A runtime implementation.

After adding dependencies, rebuild and verify the packaged artifact:

bash
./mvnw dependency:tree
./mvnw spring-boot:run

Or with Gradle:

bash
./gradlew dependencies
./gradlew bootRun

This helps confirm that the correct JAXB artifacts are actually present in the application's dependency graph.

When Modules Are Involved

If your project also uses module-info.java, then module declarations matter too. In that case, you may need module requirements as well as build dependencies. Many Spring Boot applications on the classpath do not use JPMS modules directly, so avoid adding module complexity unless the project already depends on it.

The main migration issue is usually missing dependencies, not an incomplete module-info.java.

Common Pitfalls

  • Assuming Java 9 and Java 11 behave the same way. Java 9 introduced modules, while Java 11 removed JAXB from the JDK entirely.
  • Adding only jaxb-api and forgetting a runtime implementation.
  • Using --add-modules as a permanent solution instead of declaring dependencies in the build.
  • Debugging Spring Boot configuration first when the real failure is simply a missing class on the runtime classpath.
  • Mixing jakarta.xml.bind and older javax.xml.bind dependencies without checking what the library ecosystem expects.

Summary

  • 'javax.xml.bind.JAXBException failures after moving off Java 8 usually come from JDK packaging changes around JAXB.'
  • On Java 9 and 10, --add-modules java.xml.bind can be a temporary bridge.
  • On Java 11 and later, explicit JAXB dependencies are usually required.
  • In Spring Boot, fix the build dependencies first, then verify the runtime classpath.
  • Prefer an explicit, dependency-based solution over relying on JDK-specific behavior.

Course illustration
Course illustration

All Rights Reserved.