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:
For Gradle:
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:
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:
Or with Gradle:
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-apiand forgetting a runtime implementation. - Using
--add-modulesas 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.bindand olderjavax.xml.binddependencies without checking what the library ecosystem expects.
Summary
- '
javax.xml.bind.JAXBExceptionfailures after moving off Java 8 usually come from JDK packaging changes around JAXB.' - On Java 9 and 10,
--add-modules java.xml.bindcan 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.

