1

We have maven apps that until recently were on JDK8. We just upgraded them to JDK11 and are trying to take advantage of the JPMS from JDK9 by making our utility libraries into modules.

We originally had this kind of path:

utils/some-library1/src/main/java/com/company/team/utils/lib1/Util1.java

There, java is the "source root".

So a colleague placed the module-info.java file in the lib1 folder and declared it thus:

module utils.lib1 {
    exports com.company.team.utils.lib1;
}

From the command line that builds and works, so he assumes everything is all module-y goodness.

But when I opened in Intellij, it had an ugly red line and the message said I should move it to source root. It then moved it to the "java" folder above. Fair enough.

That caused me to dig around trying to find out more about this JPMS that my colleague had implemented. After a lot of searching and experiments, I also determined that the "java" folder, as "source root", should be renamed to the name of the module ("utils.lib1"). So now I have these two files:

utils/some-library1/src/main/utils.lib1/module-info.java
utils/some-library1/src/main/utils.lib1/com/company/team/utils/lib1/Util1.java

And even Intellij is happy. Hooray! So I refactor all the other libraries. Suddenly I hit a major snag in let's call it lib2 with this line:

module utils.lib2 {
    exports com.company.team.utils.lib2;
    requires java.ws.rs;
}

Intellij flags the module with the red error squiggle again, this time saying:

Module 'utils.lib2' reads package 'javax.activation' from both 'jakarta.activation' and 'jakarta.activation'

I did some digging and found out the following:

java.ws.rs pulls in one of the following (it depends on which app):

  • javax.ws.rs-api-2.1.1.jar
  • jakarta.ws.rs-api-2.1.6.jar

Their module-info.java files contain this line:

requires transitive java.xml.bind;

Which pulls in one of:

  • jakarta.xml.bind-api-2.3.2.jar
  • jakarta.xml.bind-api-2.3.3.jar
  • jaxb-api-2.4.0-b180830.0359.jar

Which all have this line:

requires transitive jakarta.activation;

And that's where I give up. Our libraries are big hefty things that are hard to parse completely, so to simplify I created a maven app with just one class and all it does is import javax.ws.rs.core.Link.

And IntelliJ still gives that crazy error that I can't figure out and Google has been adamant in refusing to tell me.

Is it really broken or is Intellij just as confused as I?

I gave the long story both to show what we've done and to let you know that I'm very new to modules. So if it's a simple thing, please excuse me. I am just stumped though.

Additionally, are there any obvious tests one can perform at the command line to validate module configuration?

I've had inconsistent luck with jdeps, javac, and actually running as indicators of problems.

My suspicion is that things only work now because they're all in the unnamed module. But I need to get everything working if I'm going to convince anyone to change it.

EDIT

This question was reported as already answered, but that is incorrect. The suggested link deals with two different packages (A & B) importing package X. But in my case, the error is that the same package (A & A) imports package X. And this is done a few transitives down, so I have no control over the imports and can't see how to do an exclusion. Also, this problem can be repeated with just single requires statement in module-info.java!

Plus, there is a second question here that is also important that has not been addressed: how to validate the module configuration from command line (without involving the IDE at all).

Bobby Cottle
  • 85
  • 3
  • 9
  • Can you share the link to that single class file example that you have been able to reproduce the issue with? Have you made sure configurations for Maven, IntelliJ, dependency version etc. are up to date and compatible? – Naman Oct 23 '20 at 03:02
  • I cannot, as it's on my work PC. But I'm on Maven 3.6.3, openjdk 11.0.6, Intellij Ultimate 2020.2. My sample standalone project is "bsc" and here's the sole file (Main.java): `package com.company.team.bsc;` `import javax.ws.rs.core.Link;` `public class Main { Link l;}` – Bobby Cottle Oct 23 '20 at 12:50
  • Does this answer your question? [java 9 module reads package X from A and B](https://stackoverflow.com/questions/44463552/java-9-module-reads-package-x-from-a-and-b) – Andrey Oct 23 '20 at 12:51
  • And in new comment because formatting is bad here, module-info.java: ```module bsc { exports com.company.team.bsc; requires java.ws.rs; }``` – Bobby Cottle Oct 23 '20 at 12:52
  • @Andrey, I actually read that, but I had trouble understanding where all that code goes. It looks like it's all part of his module-info.java, but can that be correct? I've never seen all those things (still a noob here). Also, my problem is "module reads package X from A and A". When I've only imported a single module! This seems like there's a bug somewhere, but I'm worried it's in my head. – Bobby Cottle Oct 23 '20 at 12:57

2 Answers2

0

I also determined that the "java" folder, as "source root", should be renamed to the name of the module

No, it should not. The java source root should be left as is but you must create a package name corresponding to your module name, so it should be /src/main/java/ - source root and then utils/lib1 directory - whidh would be the package.

Andrey
  • 15,144
  • 25
  • 91
  • 187
  • Well, the package is still "com.company.team.utils.lib1", and the "com" folder must be the child of the "source root". Most sources I've read say that should be the "module folder", which is named exactly like the module. Which in that case generates this directory structure: utils.lib1/com/company/team/utils/lib1 – Bobby Cottle Oct 23 '20 at 13:00
  • Now, I could insert that module folder between "java" and "com", but it seems less intrusive to just rename "java". – Bobby Cottle Oct 23 '20 at 13:01
0

I came across exact same warning in Intellij and it was genuine. In my case the collision was coming from three separate dependencies using same module name (i.e. 'jakarta.activation'):

  • 'jakarta.activation:jakarta.activation-api:1.2.2'
  • 'javax.activation:javax.activation-api:1.2.0'
  • 'com.sun.activation:jakarta.activation:1.2.2'

It got it resolved for my project by applying explicit exclusions on dependencies which were pulling the last two.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Can you show the exclusion code? And preferably some command line tests for JPMS module validity (but at this point I'm not too picky). I created a new Intellij "module" with just one class that required `java.ws.rs`. It did no actual work, no other imports. And it had that error. But when I opened that same folder as an Intellij "project", the error was gone! Even though it has no maven connection to the other modules in my project, the error shows up when it's part of the same Intellij project, but not as a standalone. – Bobby Cottle Oct 26 '20 at 12:39