Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JDK 9: JUnit 5 test compile with SpringExtension produces java.lang.NoClassDefFoundError: org/w3c/dom/ls/DocumentLS

I believe this problem not to be related to module exclusions in JDK 9 (as with java.se.ee), but rather with the fact that JDK 9 includes a newer version of org.w3c.dom.ls in the java.xml module that does not have the DocumentLS class.

The important bit of the stack trace is this:

Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [spring-test/test-container.xml]; nested exception is java.lang.NoClassDefFoundError: org/w3c/dom/ls/DocumentLS
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:414)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)

Even if I include a runtime dependency with this class, like xerces:xerces 2.4.0, the JDK java.xml module is preferred (I guess).

I am using Gradle 4.1. Is there any way to restrict the scope of a JDK provided module?

like image 517
Christopher Johnson Avatar asked Aug 16 '17 21:08

Christopher Johnson


1 Answers

As you have correctly analyzed, the package org.w3c.dom.ls is present in the platform module java.xml. Any class on the class path that is in the same package will be ignored. That's called a split package and several fixes exist - the following two might help you.

Patch java.xml

You can add the classes of the Xerxes JAR to the java.xml module with --patch-module:

java --patch-module java.xml=xerxes-4.0.0.jar ...

I've never tried that with a JAR that contains some of the same classes. As I understand it, the JDK classes will then be replaced with the Xerxes classes, which means they better be a fully binary compatible replacement.

Upgrade java.xml

Another hope is to replace java.xml with the upgrade module path:

The upgrade module path (--upgrade-module-path) contains compiled definitions of modules intended to be used in place of upgradeable modules built-in to the environment (compile time and run time).

You face two problems:

  • the upgrade module path is supposed to be used only for upgradable modules (which java.xml is not), but I think I've read somewhere that that's not enforced (yet?) - didn't try it
  • the artifact you replace java.xml with needs to be fully binary compatible update - would that be the case for Xerxes?
like image 116
Nicolai Parlog Avatar answered Dec 01 '22 12:12

Nicolai Parlog