I'm developing on a Maven project (branch platform-bom_brussels-sr7) in Eclipse. When I recently tried switching the Java Build Path for the project to JDK 10, Eclipse build can no longer find classes such as javax.xml.xpath.XPath
, org.w3c.dom.Document
, or org.xml.sax.SAXException
. It seems only XML related classes are impacted, mostly from the Maven dependency xml-apis-1.4.01
.
Trying a Maven build from Eclipse works without errors. Ctrl-LeftClick on one of the supposedly missing classes finds the class and opens it in the Eclipse editor. It seems only the Eclipse build is impacted.
I tried several things, but none helped. I tried:
I assume that the project being migrated from Java 1.8 still has no module-info.java
. This implies you are compiling code in the "unnamed module".
Code in the unnamed module "reads" all observable named and unnamed modules, in particular it reads module "java.xml" from the JRE System Library. This module exports package like java.xml.xpath
.
Additionally, you have xml-apis.java
on the classpath, which contributes another set of packages of the same names (java.xml.xpath
and friends). These are said to be associated to the unnamed module, like your own code.
This situation violates the requirement of "unique visibility" as defined in JLS §7.4.3 (last paragraph). In particular every qualified type name Q.Id (JSL §6.5.5.2) requires that its prefix Q is a uniquely visible package (I'm disregarding the case of nested types for simplicity). Ergo: the program is illegal and must be rejected by compilers.
This leaves us with one question and two solutions:
(1) Question: Why is javac accepting the program?
(2) Solution: If you add module-info.java
to your project, you can control via requires which module your project reads, either requires java.xml;
or requires xml.apis;
(where "xml.apis" is the automatic module name of "xml-apis-1.4.01.jar).
(3) Solution: Short of turning your project into a module, you can still avoid the conflict by excluding java.xml
from the set of observable modules. On the command line this would be done using --limit-modules
. The equivalent in Eclipse is the "Modularity Details" dialog, see also the JDT 4.8 New&Noteworthy (look for Contents tab). Since java.xml
is implicitly required via a lot of other default-observable modules, it may be a good idea to push everything except for java.base
from right ("Explicitly included modules") to left ("Available modules") (and selectively re-add those modules that your project needs).
PS: Eclipse still doesn't provide an ideal error message, instead of "cannot be resolved" it should actually say: "The package javax.xml.xpath is accessible from more than one module: javax.xml, <unnamed>.
PPS: Also weird: how come that changing the order between JRE and a jar on the classpath (such ordering is not a concept supported by javac nor JEP 261) changes the behavior of the compiler.
EDITs: