8

I want to migrate from Java 8 to Java 9. When running my tests I get a CNFE regarding javax.xml.bind.JAXBContext. Therefore, "--add-modules java.xml.bind" seems to be required. I tried to extend my GRADLE_OPTS env variable, but the error remains. Any hint is appreciated.

Juergen Zimmermann
  • 2,084
  • 7
  • 29
  • 43
  • Did you take a look at [How to express dependency in maven on java ee features for transition to Java 9?](https://stackoverflow.com/questions/46084751/how-to-express-dependency-in-maven-on-java-ee-features-for-transition-to-java-9/46086920#46086920) ? Could you detail your setup otherwise please. – Naman Oct 28 '17 at 15:43
  • It's a runtime failure, and not a compilation issue. I'm using Kotlin (not Java) and Spring Boot. @nullpointer: Does it mean, that I've only to adapt the 2nd part of your answer? – Juergen Zimmermann Oct 29 '17 at 00:20
  • Yes, just the test execution phase, in that case, should be the change required for you. – Naman Oct 29 '17 at 00:51
  • 2
    To add to @nullpointer's comment. Java SE has deprecated the java.xml.bind module for removal. This means that `--add-modules java.xml.bind` is a short term workaround and you'll have to re-visit it. Better to move to the standalone API/implementation (javax.xml.bind:jaxb-api:2.3.0 and org.glassfish.jaxb:jaxb-runtime:2.3.0). – Alan Bateman Oct 29 '17 at 05:57

2 Answers2

4

You can follow the five basic steps while migrating as stated in the gradle-building java9 modules which are:-

When converting a java-library project to produce a Java 9 module, there are five changes you should to make to your project.

  • Add a module-info.java describing the module.

  • Modify the compileJava task to produce a module.

  • Modify the compileTestJava task to locally alter the module.

  • Modify the test task to consume the locally altered module.

  • (Optional) Add Automatic-Module-Name manifest entries for all other projects.


In your use case, you need to ensure that the

compileTestJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath, 
            '--add-modules', 'org.junit.jupiter.api',  // junit5 automatic module specific
            '--add-modules', 'java.xml.bind', // jaxb specific
            '--add-reads', "$moduleName=org.junit.jupiter.api", // allow junit to read your module
            '--patch-module', "$moduleName=" + files(sourceSets.test.java.srcDirs).asPath, // add test source files to your module

        ]
        classpath = files()
    }
}

and then for executing the test, you would need not to udpate the test task as

test {
    inputs.property("moduleName", moduleName)
    doFirst {
        jvmArgs = [
            '--module-path', classpath.asPath, 
            '--add-modules', 'ALL-MODULE-PATH', // to resolve all module in the module path to be accessed by gradle test runner
            '--add-reads', "$moduleName=org.junit.jupiter.api", 
            '--patch-module', "$moduleName=" + files(sourceSets.test.java.outputDir).asPath, 
        ]
        classpath = files()
    }
}

Note: For a long-term solution though I would also suggest you follow the important point mentioned in this answer as well.

saw303
  • 8,051
  • 7
  • 50
  • 90
Naman
  • 27,789
  • 26
  • 218
  • 353
3

According to Alan Bateman, I added the following lines to build.gradle so that gradle bootRun also works:

runtime('org.glassfish.jaxb:jaxb-runtime:2.3.0', 'javax.activation:activation:1.1.1')
Naman
  • 27,789
  • 26
  • 218
  • 353
Juergen Zimmermann
  • 2,084
  • 7
  • 29
  • 43