Reputation: 4334
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:
Upvotes: 85
Views: 83123
Reputation: 8178
While the accepted answer (by myself) is still correct, a further twist of the story was recently brought to my attention:
The original intention may have been to actually support the situation at hand.
See this quote in the original design document "The State of the Module System" (SotMS):
If a package is defined in both a named module and the unnamed module then the package in the unnamed module is ignored.
That document is dated 2016/3/8 08:18, and already at that time was marked "This document is slightly out of date". Moreover, it is not legally binding for any implementation. Still that document has some relevance since what's quoted above is precisely what javac
appears to implement (and still implements many years after JDK-8215739 was filed).
IOW, the conflict is not so much a conflict between 1st and 2nd implementation, but a conflict even within Oracle, so it seems. 2 Votes for supporting the situation (SotMS and javac) and only one vote for disallowing (JLS).
Since Eclipse committers are not inclined to resolve this conflict within Oracle, the recent 2022-12 release of Eclipse has a new compiler option: by adding the following line to a project's .settings/org.eclipse.jdt.core.prefs
, a user may opt to ignore JLS in this regard:
org.eclipse.jdt.core.compiler.ignoreUnnamedModuleForSplitPackage=enabled
This option puts the decision into the user's hands: do they want JLS-semantics or SotMS/javac semantics (in this particular issue)? Still we were not quite ready to provide a UI option for it, to avoid that users made this choice thoughtlessly, without the background information as provided here.
Personally, I'm not particularly happy about this situation, as it aggravates the fact that Java is not one, but several languages (blog post written by me).
Upvotes: 14
Reputation: 8178
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:
Upvotes: 120
Reputation: 43
Thanks for this clue. I was having trouble identifying where the conflicting reference was coming from for org.w3c.dom.Document. Found it easily in Eclipse 2020-12 this way: Selected org.w3c.dom.Document within the import statement that Eclipse flagged, right-click and choose Open Type Hierarchy, in the Type Hierarchy dialog right click Document at the top and choose Implementors > Workspace to reveal all the JARs in all projects in the workspace which are bringing in org.w3c.dom.Document (or whatever type you have selected that is accessible from more than one module – MikeOnline yesterday
following the directions above from one of the earlier posts helped us solve our issue. what we did was replace Document with GenericDocument and Element with GenericElement from batik - and compile errors are gone - now we just have to test to make sure the implementation matches what we had under java 8. Thanks MikeOnline
Upvotes: 2
Reputation: 14671
In my case the problem was that xercesImpl : 2.10.0
was a (transient) dependency. This jar bundles org.w3c.dom.html.HTMLDOMImplementation
.
As far as I understand the org.w3c.dom
package then becomes available from two modules, causing the build to fail.
In case one of the dependencies (direct or transient) has classes in one of the 25 packages exported by the java.xml module your build will fail.
Excluding xercesImpl (and also the offenders listed below) in Maven solved the issue for me:
<dependency>
<groupId>xyz</groupId>
<artifactId>xyz</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
...
</exclusion>
</exclusions>
</dependency>
Thanks to Rune Flobakk for giving the hint here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=536928#c73
Other offenders:
batik-ext : 1.9
(bundles org.w3c.dom.Window)xom : 1.2.5
(bundles org.w3c.dom.UserDataHandler)stax-api : 1.0.2
(bundles javax.xml.stream.EventFilter)xml-apis : 1.4.01
(bundles org.w3c.dom.Document)xml-beans : 2.3.0
(bundles org.w3c.dom.TypeInfo)Upvotes: 14
Reputation: 1603
While Stephan Herrmann's answer is the correct one, I'll post my error and how I got it solved if it can help others. I had the error The package javax.xml.namespace is accessible from more than one module: <unnamed>, java.xml
and after inspecting the class with the error, it was the javax.xml.namespace.QName
import that was complaining. With the "Open Type" dialog, I found out that it was pulled from stax-api
through eureka client. This solved it for me :
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
Upvotes: 5
Reputation: 17028
What happens here is you have a wildcard import like import org.w3c.dom.*
, stating you want to import all classes from package org.w3c.dom
. Now, if there's at least one class in org.w3c.dom
provided by a second source, Java must not start (as pointed out here).
(By the way, the message "... cannot be resolved" is replaced by a more accurate error message "The package org.w3c.dom is accessible from more than one module: <unnamed>, java.xml" in more recent Eclipse versions, see this merged change request by Stephan Herrmann.)
To resolve this problem
org.w3c.dom.*
or org.w3c.dom.
.pom.xml
.pom.xml
manually).Example
I had this findbugs dependency in my pom.xml
:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs</artifactId>
<version>${findbugs.version}</version>
</dependency>
Findbugs has two dependencies that need to be excluded:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs</artifactId>
<version>${findbugs.version}</version>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</exclusion>
</dependency>
Upvotes: 5
Reputation: 10931
Have seen something very similar under Eclipse 4.8.0 and JDK 10. E.g.
import org.w3c.dom.Element;
was failing to compile in Eclipse with: The import org.w3c.dom.Element cannot be resolved
Even so, pressing F3 (Open Declaration) on that import, Eclipse was able to open the interface definition - in this case under xml-apis-1.4.01.jar
.
Meanwhile, builds from Maven direct were working fine.
In this case the fix was to remove this dependency from the pom.xml
:
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
Then the compile errors in Eclipse melted away. Following F3 again showed the Element
interface - now under the java.xml
module, under the JRE System Library under the project. Also the Maven build remained fine.
This feels like a problem with Eclipse resolving a class that it finds in both a JDK module and dependent .jar file.
Interestingly, in a separate environment, this time under Eclipse 4.9.0 and JDK 11, all is fine, with or without the xml-apis:1.4.01
dependency.
Upvotes: 4
Reputation: 159
This is more of a work-around, but from my experience it can be resolved by going to the "Java Build Path", the "Order and Export" tab, and sending the "Maven Dependencies" to the bottom (so it's below the "JRE System Library").
Upvotes: 3
Reputation: 21456
This seems to have been reported as Eclipse Bug 536928. Maybe if everyone were to go vote on it it would get them to raise the priority.
Upvotes: 5
Reputation: 1611
jdk 9+ brought in changes related to project jigsaw. JDK was broken down into various modules and some modules, javaee, jaxb and xml related, are no more loaded by default. You should add these to your maven build directly, instead of expecting them to be in jre classpath. see this SO question
Upvotes: 0