What do I need to build JDK 9 project with non-modular dependencies using Maven
Asked Answered
M

3

18

I have a simple Java 9 SE project with one dependency on a non-modularized project (chose Weld SE for this example) and I am trying to build it with Maven (clean install).In order for Java 9 to kick in, I have added module-info.java. Originally, this file only contained module name and had no requires formulas.

Please bear in mind that my sole dependency is NOT a modular project, therefore I presumed Maven will put in the classpath (not module-path) and hence it will end up in the unnamed module as described in State of the modular system.

Now, my Maven version is 3.3.9 and I am aware that I need to use Maven compiler plugin in version 3.6, as described here Of course I have downloaded JDK 9 EA build with jigsaw and set Maven to use that.

If I build my project without module-info.java, everything works, stuff is added to classpath and build succeeds. I suppose Maven just sticks to the old ways as long as you leave out that file.

However building it with module-info.java tells me that the classes from my dependency cannot be found on the classpath. So I ran Maven in debug mode (with -X) and indeed - all jars are under module-path and classpath is empty. This effectively means that all my dependencies are transferred into automatic modules and I need to declare them in module-info.java.

Once I declare the automatic module requirements(link to projects's module-info), I am able to build it on JDK 9. But it is kind of messy - my only pom.xml dependecy is on weld-se-core, yet my module-info requires me to declare a lot more requirements for compilation to pass.

Here is a whole GitHub project where all this can be observed.

So my questions are:

  1. Can I tell Maven to put some artifacts on classpath if I know they are not modularized? So that I can avoid the automatic module and the need to declare them?
  2. If I stick with automatic module, can I tell Maven to somehow transitively allow anything my dependency needs to bring in? E.g. other parts of Weld, CDI API etc.
  3. What is the actual reason, why I need to state, that my project requires modules, which I do not use directly? E.g. weld.environment.common
Misanthropy answered 8/11, 2016 at 15:19 Comment(6)
That page is a bit outdated, the compiler plugin 3.6.0 is now out. Are you using this release version? Could you post your current project, and a sample POM?Luckey
Forgot to add - I am aware that its outdated and I use released versions where applicable. I'll create a simpler version of the project and update the question by tomorrow. But basically I took this project and tried to turn it into JDK 9 aware one. (by adding module-info and updating those maven plugins)Misanthropy
Did you check that page as well? You need to define 2 execution blocks for projects that are Java 8 compatibleLuckey
Can't help you with the Maven details but there's one thing you got wrong. All of your module's dependencies need to be declared in the module-info.java, even if they are not modules themselves. Those that are not modules must still be placed on the module path to be turning them into automatic modules.Mickiemickle
@Luckey Good link, thanks. I checked it and while it made few things clear, it didn't help.Misanthropy
@NicolaiParlog With your comment I actually managed to get it working. But it only raised more questions for me. I have updated the question. I don't really understand why Maven behaves in this manner, why do I get automatic module instead of unnamed module. And why I need to declare requirements for modules I do not use directly :-/Misanthropy
L
2

Including few of the recent updates, I would try and answer this.

UPDATE

  • Java 9 was released publically on 21.09.2017.

  • The minimum compatible version of maven-compiler-plugin in today's date is 3.7.0.

    As already shared by @Tunaki on how you can configure it to build compatible versions for both JDK 1.5 to 8 and JDK 9.

Assuming from the question and comments, you are already aware of automatic modules and placing all the module dependencies on the module path.

Can I tell Maven to put some artifacts on classpath if I know they are not modularized? So that I can avoid the automatic module and the need to declare them?

For artifacts specified in the maven pom <dependencies> and the ones which are as well not included in the module-info.java of the current module are ultimately left behind to be accessed from the classpath in form of an unnamed module.

If I stick with automatic module, can I tell Maven to somehow transitively allow anything my dependency needs to bring in? E.g. other parts of Weld, CDI API etc.

No, since the automatic modules do not consist of an explicitly declared module-info.java, there is no such way of defining requires transitive for any transitive dependency that might be required by the present module.

From one of my past experiences, any Maven transitive dependency as detailed in the dependency:tree that is needed at compile time by the module would have to be explicitly defined using requires in the module-info of the current project.

What is the actual reason, why I need to state, that my project requires modules, which I do not use directly? E.g. weld.environment.common**

  • You do not need to specify requires for modules that are not required at compile or runtime by your module.

  • In case there is a dependency that is not required at runtime but required at compile time by your project, you would need to make sure that you define such module using requires static in your declarations.

    I would have preferably practiced a similar approach at present as well, as stated in the answer to should I keep or remove declared dependencies that are also transitive dependencies?

Liggins answered 4/10, 2017 at 18:5 Comment(3)
I pretty much figured all I asked some (long?) time ago, but I forgot that I asked this in the first place - shame on me. Your answer sums it up nicely, I'll accept it.Misanthropy
For maven-compiler version 3.7.0 just have in mind this issueErmines
@MarinosAn I see for the compatibility issue that you are pointing out. Thanks for sharing. I guess I moved to 3.8.0 and above for related compatibility issue and updated JDKs on personal projects.Liggins
S
1

I think this may help to tell maven to use java 9 :

    <build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
                <source>9</source>
                <target>9</target>
            </configuration>
        </plugin>
    </plugins>
</build>
Supernatant answered 1/11, 2017 at 13:15 Comment(0)
H
0

If you specify a module-info.java file, you will need to declare all the java modules except java.base you need as you are now using jigsaw.

Using mvn dependency:tree can help you in populating this but you are not required to use module-info.java in Java 9.

Hb answered 31/7, 2017 at 22:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.