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:
Project Clean
Different Eclipse Versions: Oxygen and Photon.
Running Eclipse itself with JDK 8 and JDK 10.
Changing Compiler Compliance level for the project. It builds with compliance level 8 and 10 under JDK 8 build path and fails for both with JDK 10 in build path.
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:
Alex Buckley confirmed that the given situation is illegal, despite what javac says. Bug against javac has been raised as JDK-8215739. This bug has been acknowledged months before the release of Java 12. As of 2019-06 it has been decided that also Java 13 will ship without a fix. Similarly for Java 14. The bug was temporarily scheduled for Java 15, but this plan has been dropped on 2020-04-20.
Eclipse error message has been improved to mention the real problem.
In Eclipse 2019-06 the UI used for Solution (3) has been revamped. Up-to-date documentation can be found in the online help.
As of 2022-12 there's yet another perspective on this issue as described in my other answer. It doesn't invalidate what's said here, but let's things appear in a different light.
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)
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.
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.
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
Open the "Open Type" dialog (Ctrl+Shift+T).
Enter the complete import, so org.w3c.dom.* or org.w3c.dom..
Check the entire list for multiple sources. All entries here should contain only something like "jdk-11-...".
Gather all JARs that contain classes you have multiple sources for.
Open the "Dependency Hirarchy" tab from pom.xml.
Search for the JAR file.
Add an exlusion (right click or edit the 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>
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>
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.
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").
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
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
I am very new to programming, and while working on my first software development project I came across the error: "package javax.activation is not visible." I have read other posts that have said that in order to fix the error, one must add a dependency to the module path?
Because I'm just starting out, I really don't know what this means and how to go about that, and was wondering if someone could point me in the right direction? Thanks in advance. (I'm also using JGrasp if that matters)
Broadly speaking, a dependency is code (often written by someone else) which your application needs to compile.
A dependency in your case, is a java library which has classes that need to be on your class path. You can find more about class paths here: https://docs.oracle.com/javase/tutorial/essential/environment/paths.html. In order to overcome error mentioned in a question, you need to have javax.activation module dependency on your class path.
You could do it in few ways. In the majority of IDEs (in your case we are talking about JGrasp) there is a way to add a dependency to the project directly. Then, your IDE would compile the code with given dependency on a class path and problem would be solved. And that would be the first and most beginner-friendly way, unfortunately I haven't a faintest idea about JGrasp so I'm going to focus on other solutions.
The second way you could do this is to build your program with build automation tool, such as Apache Maven or Gradle. You should definitely check those guys out, as they are insanely useful when it comes to building Java code and, sooner or later, you will probably start using them anyway. Let's say you have chosen Apache Maven. In your project you would then have a pom.xml file and you would simply look-up the needed dependency in Maven Central repository, add it to your dependencies section in pom.xml file and build the application. Your pom would look something like this:
<project>
...
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
</dependencies>
...
</project>
Of course Apache Maven is not a lightweight tool so you would have to take some time to learn how to build code with it. I recommend starting with this tutorial:
https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html
I also encourage you to get your hands on Apache Maven docs, as it is quite readable and transparent.
And the last way I can think of is to manually compile your application and include the required dependency during the compilation process. There are plenty of tutorials on SO that tell you how to do this, so I'll simply summarize and indicate the resources. What you need to do is to find the required dependency jar package. You will want to search the maven central repository (see: https://mvnrepository.com/) and from there download your .jar file. The next thing you need to do is to learn how to compile your Java code to .class files including the downloaded jar. To acquire such a wonderful skill, please see this one: How to include jar files with java file and compile in command prompt
Amongst those three ways, the recommended one is to get to know with build tools such as Apache Maven or Gradle. Hope I helped you! Good luck
This question already has answers here:
Maven assembly : add different version of the same artifact
(4 answers)
Closed 8 years ago.
I need to add the same dependency twice configuring one version for the compilation and test purpose and another version of the same library for the runtime.
It sounds weird and it is wrong but I received 2 version of the same library from another team in my company and the "test purpose" version contains some classes - used only by the "test" methods - that haven't to be expose in a production server because very sensible being part of the 'core'. So this means I need to use a version library for the test and compilation phase and another one only on the server.
Actually I solved the problem setting only the "test" version with 'provided' scope, so it won't be included in the generated war, and putting the "production" version in the web container's lib folder but my boss wants I will automate the configuration!!!
Unfortunately if I add the dependency to the second version with 'runtime' or 'compile' scope maven doesn't find the classes present only in the "test" version during the JUnit execution step. It seems like Maven recognises the libraries like the same and the 'compile' or 'runtime' configuration won on the other one. I've tried also to set the "test" version with 'test' scope but it doesn't work either... actually I've tried all the possible combinations using 'test' and 'provided' scopes for the "test" version and 'runtime' and 'compile' for the "production one.
Any suggestion? I can't ask for a different library only for test purposes or just to change the name of the library, everything is integrated with a continuous integration system and it has to be automated with it, so annoying...
<dependency>
<groupId>company.group.id</groupId>
<artifactId>project.id</artifactId>
<version>0.1.1.TEST</version>
<scope>provided</scope>
//<scope>test</scope>
</dependency>
<dependency>
<groupId>company.group.id</groupId>
<artifactId>project.id</artifactId>
<version>0.1.0.PROD</version>
<scope>compile</scope>
//<scope>runtime</scope>
</dependency>
Thanks
Peter Lawrey says in this link,
"Maven assumes it doesn't make any sense to have more than one version of a module at once. It assumes that a newer version replaces the older version. If it doesn't it is not the same module. I suggest you give the newer module a different name and make sure it has different packages to avoid choising a random module.
In general Maven tried to encourage good application design and deliberately makes it difficult to do things it has determined to be a bad idea."
I just produced my first parent-module project with maven, and successfully installed it. Can I add this project as a dependency in another project, only by referring to the parent? My Eclipse IDE complains that it can't find the parent.jar, but that is not a surprise, as it is packaged as parent.pom.
Question:
So is it possible to add a parent (.pom) dependency, and get all transitive dependencies for free, or do I have to add .jar's.
Bonus Question:
Is it possible to add dependencies to other packaging formats as well, like a war? I can't really figure out how that would work, or why I would need that at this point though. Just curious.
Disclaimer:
I'm still learning maven, and find the philosophy and theory of it to be great. However, there are so many pits and reefs that seems to pop out, and more than once, I struggle to see if I'm trying to do something impossible, or if there is another mistake in configurations I.E. Right now Eclipse says it can't find any of my .m2 referenced dependencies in this one particular project. I have no idea why, as other projects works fine. I am in other words trying to find the error, by checking one area at the time...
Answer: Yes, you can add different types such as pom, test-jar and so on. Jar is just the default
Bonus Answer: Yes, you can specify type war as well
The Maven-Guide defines the following types: "The current core packaging values are: pom, jar, maven-plugin, ejb, war, ear, rar, par."
Here is a example on how a POM is included:
<dependencies>
<dependency>
<groupId>com.my</groupId>
<artifactId>comm-group</artifactId>
<type>pom</type>
</dependency>
</dependencies>
This (the pom of comm-group) is oftenly used to group certain dependencies and include all of them using the type-pom.
Here is additional information on grouping: http://blog.sonatype.com/2009/10/maven-tips-and-tricks-grouping-dependencies/#.VFC7LR_JY8c Note that there are similar behaviours you could create using polymorphism.
I had my issues with maven when we migrated from Ant and i still have certain concernes on it (like were is the advantage of maven if 80% of our SWEs apply wrong scopes, types and so on leading to a massive drawback if they just 'need to add a fcking jar' as well as to refactorings lead by "maven gurus").
BUT: I can guarantee you that if you go throught http://maven.apache.org/pom.html completely you will aquire statisfieing results compared to ANT over time.
Update: I just ran into the case where my pom could not be included on the remote build server while it worked building it from inside Intellij Idea/ Eclipse. Type definition in my case had to be lowercase (e.g. 'pom' instead of 'POM').
I have a Maven project (ejb container) where I need to use the jcifs library.
I made the entries in pom.xml like:
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
<type>jar</type>
</dependency>
Everything is okay, I see the jar file inside the ear package, I see it also in the dependencies of the project, I can use the classes but at runtime I get:
javax.ejb.EJBException: java.lang.RuntimeException: java.lang.NoClassDefFoundError: jcifs/smb/SmbFile
at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:63)
What am I doing wrong?
Right-click the webproject and go to properties -> Java EE Module Dependencies. Check the Maven dependencies is checked.If not check and redeploy .
I would like to help the people who are as stupid as I am. This is not really the about the same scenario as asked for in this question, but this question helped me to figure out my problem.
I wrote a little code in a scratch file, in my case in Intellij. Before that I added the jcifs dependency to my maven project, assuming that the scratch file would find it there, which in hindsight is a bit stupid, because how would the scratch space know.
So my hint is to have a look where the dependency will actually have an effect, i.e. is available - compile time, runtime, scratch space?
Also I wanted to mention that I used this library, which works very fine for me https://github.com/hierynomus/smbj.
So in my case I edited the run configuration so that it would take the maven modules configuration into the classpath.
So my guess is that #SANN3 's answer is correct for the actual question.