Java 11 Eclipse finds automatic module, Maven does not - maven

I'm attempting to upgrade a 15 year old Maven multimodule project to Java 11, and the module system that was introduced in Java 9. Since the project is built using Maven, all dependencies are pretty clear. First I want to do this using the automatic module names, in order not to also introduce upgraded artifacts (if not absolutely required).
Eclipse is pretty helpful in this process, autocompleting the automatic module names in the module-info.java. For example:
requires dom4j;
But if I compile with Maven, I get errors about that it cannot find the modules Eclipse just autocompleted in there.
module-info.java:[29,18] module not found: dom4j
I am using Maven's compiler plugin 3.7.0 (3.8.0 gives a NullPointerException as per https://jira.apache.org/jira/browse/MCOMPILER-355) I suspect Maven is setting the jars up on the classpath instead of on the modulepath, but the compiler's plugin debug output does not log that.
How can I make Maven correctly handle those modules?

I was running into the same issue. Adding
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
to my pom solved the problem for me...
Maven version 3.9.0 seems to be buggy and will not find the module although the dependency is using an Automatic-Module-Name. Downgrading to version 3.8.1 helps.

Related

I want maven to use JRE system Library [JavaSE 1.8] always while creating new maven quickstart project

I have jdk/jre 1.8 installed on my windows system. In Eclipse whenever I create a quick-start maven project, the project gets created with JRE System Library[J2SE 1.5]. I am fed up of this problem tried to change the execution environment by doing right click on above JRE library-properties and changing the execution environment to 1.8 but again if I update this maven project, the JRE system library goes back again to J2SE 1.5, I also tried changing the compiler compliance to 1.8 which was earlier set to java 10 and also did adding the source and target tag with version 1.8 inside plugin tag of pom.xml but this was also a temporary solution. As when I create a new maven project it sets the default JRE system Library[J2SE 1.5]. Please Provide me with a permanent fix where whenever i create a new maven project, it should be created with JRE System Library[JavaSE 1.8].
Add the following to pom.xml to configure which JDK version you would want to use:
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
or the followings:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
It is because when you do Maven --> Update Project in Eclipse , Eclipse 's maven plugin will use what you define in pom.xml to update the setting of the eclipse project. If you don't specify above settings , the default is to use JDK 1.5 (before maven-compiler-plugin version 3.8.0) or JDK 1.6 (3.8.0+)
Basically I want maven to use JDK 1.8 by default. So that i wont need
to change pom.xml contents again and again while making a new project
If you do not want to change any settings related JDK version in pom.xml after creating a project , you may consider to create your own archetype to fully customize what pom.xml looks like after creating an project. Or a more simple way is to search some Java8 archetype created by others and simply use it such as this.
Refer this for how to create a Maven project with an specific archetype using Eclipse. You may probably need to click "Add Archetype" to configure the require information when you use that archetype for the first time. For example , for this archetype, you have to configure the following for the 1st time:
archetypeGroupId=pl.org.miki
archetypeArtifactId=java8-quickstart-archetype
archetypeVersion=1.0.0

Confusion on maven compiler plugin

I am quite confused about maven compiler plugin and what it does. I have a project that has several modules. In my top pom.xml I have a section
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
My understanding is this specifies the JDK compiler version used to compile the code, and this section get inherited by all the modules. What I don't get is in my IntelliJ IDEA I can still specify project JDK in the settings and it seems like that setting overrides this. When I run maven install in the IDE I can confirm that it is using javac from JDK 8 to compile. So what does this section do exactly?
You are correct; maven-compiler settings should be inherited by child modules.
I don't know about IntelliJ, but I can tell you that Eclipse picks&chooses whatever it wants from maven config, and for all the rest it uses its own settings.
Therefore, I'd expect IntelliJ may do something similar?
The simplest way to test this is to run a mvn clean install via command line, and see which "wins". If you get artifact compiled with 1.8 then it means you're missing something in Maven config which causes those settings not to propagate to children. If you get artifact compiled with 1.7 then it is IntelliJ who does it and not maven-compiler-plugin.

mvn clean tomcat:run command

When I run "mvn clean tomcat:run" (without specifying any tomcat version) command from command prompt for running my web application, it download tomcat 6.0.29 version dependency as shown below:
org/apache/tomcat/juli/6.0.29/juli-6.0.29.pom
org/apache/tomcat/annotations-api/6.0.29/annotations-api-6.0.29.pom
org/apache/tomcat/catalina-ha/6.0.29/catalina-ha-6.0.29.pom
org/apache/tomcat/coyote/6.0.29/coyote-6.0.29.pom
org/apache/tomcat/tribes/6.0.29/tribes-6.0.29.pom
org/apache/tomcat/jasper-el/6.0.29/jasper-el-6.0.29.pom
org/apache/tomcat/dbcp/6.0.29/dbcp-6.0.29.pom
pom.xml file of the application does not contain any tomcat version it require to run
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<finalName>esa</finalName>
</build>
So my query is how does it decide to download particular this tomcat version dependency.
Probably the default settings of the tomcat plugin you run.
Try running mvn tomcat:help -Ddetails to see what version of the plugin you use, and how it can be configured.
I think it is an earlier version of the plugin, and you can now use explicit versions, such as
mvn org.apache.tomcat.maven:tomcat6-maven-plugin:2.0:run
mvn org.apache.tomcat.maven:tomcat7-maven-plugin:2.0:run
(or the shorter form)
Seems, you are running the tomcat-maven-plugin from codehaus, whihc has tomcat 6.0.29 built-in. (Seems there was no activity since 2010.)
You should try the tomcat7 plugin from apache.
Regards
Tibor
In command line for maven use --debug option to get explanation of build process. For our case output looks like:
...[DEBUG] Resolving plugin prefix tomcat from [org.apache.maven.plugins, org.codehaus.mojo]
...
[DEBUG] Resolved plugin version for org.codehaus.mojo:tomcat-maven-plugin to 1.1 from repository central (http://repo.maven.apache.org/maven2, releases)...
Actually to explain why we've got tomcat v1.1 without specifying anything about tomcat, remember that maven build process has been customized with build plugins. And each build plugins has own build plugins. So it is enough to examine effective pom file to get clear understanding that almost empty initial pom.xml has quite big effective pom.xml.
To overcome issue just use explicit version of the tomcat plugin.

What is the difference in Maven between dependency and plugin tags in pom.xml?

Created project with Spring, Hibernate & Maven. My question is what is the logic behind plugin versus dependency ?
Both plugins and dependencies are Jar files.
But the difference between them is, most of the work in maven is done using plugins; whereas dependency is just a Jar file which will be added to the classpath while executing the tasks.
For example, you use a compiler-plugin to compile the java files. You can't use compiler-plugin as a dependency since that will only add the plugin to the classpath, and will not trigger any compilation. The Jar files to be added to the classpath while compiling the file, will be specified as a dependency.
Same goes with your scenario. You have to use spring-plugin to execute some spring executables [ I'm not sure what spring-plugins are used for. I'm just taking a guess here ]. But you need dependencies to execute those executables. And Junit is tagged under dependency since it is used by surefire-plugin for executing unit-tests.
So, we can say, plugin is a Jar file which executes the task, and dependency is a Jar which provides the class files to execute the task.
Hope that answers your question!
Maven itself can be described as food processor which has many different units that can be used to accomplish different tasks. Those units are called plugins. For example, to compile your project maven uses maven-compiler-plugin, to run tests - maven-surefire-plugin and so on.
Dependency in terms of maven is a packaged piece of classes that your project depends on. It can be jar, war etc. For example, if you want to be able to write JUnit test, you'll have to use JUnit annotations and classes thus you have to declare that your project depends on JUnit.
Plugins and dependencies are very different things and these are complementary.
What plugins are ?
Plugins perform tasks for a Maven build. These are not packaged in the application.
These are the heart of Maven.
Any task executed by Maven is performed by plugins.
There are two categories of plugins : the build and the reporting plugins :
Build plugins will be executed during the build and they should be configured in the <build/> element from the POM.
Reporting plugins will be executed during the site generation and they should be configured in the <reporting/> element from the POM.
According to the maven goal specified in the command line (for example mvn clean, mvn clean package or mvn site) , a specific lifecyle will be used and a specific set of plugins goals will be executed.
There are three built-in build lifecycles: default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project's site documentation.
A plugin goal may be bound to a specific phase of a specific lifecyle.
For example the maven-compiler-plugin binds by default the compile goal to the lifecycle phase: compile.
Most of maven plugins (both core plugins and third party plugins) favor convention over configuration. So these generally bound a plugin goal to a specific phase to make their usage simpler.
That is neater and less error prone :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
than :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
What dependencies are ?
Dependencies are Maven artifacts/components required for the project.
Concretely most of dependencies are jar (that is libraries) but these may also be other kinds of archives : war, ear, test-jar, ejb-client ... or still POM or BOM.
In a pom.xml, dependencies may be specified at multiple places : the <build><dependencies> part , the dependencies management part or still in a plugin declaration ! Indeed some plugins may need to have some dependencies in the classpath during their execution. That is not common but that may happen.
Here is an example from the documentation that shows that plugin and dependency may work together :
For instance, the Maven Antrun Plugin version 1.2 uses Ant version
1.6.5, if you want to use the latest Ant version when running this plugin, you need to add <dependencies> element like the following:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
...
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
</project>
In Maven, dependencies are referenced in a specific format :
groupId:artifactId:packaging:classifier:version.
The classifier (that is optional) and the packaging (JAR by default) are not commonly specified. So the common format in the dependency declaration is rather : groupId:artifactId:version.
Here is an example of dependency declared in the <build><dependencies> part :
<build>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.14.Final</version>
</dependency>
<dependencies>
</build>
Dependency doesn't have a phase binding as plugins to address the "when" question.
But it has a counterpart : the scope.
Indeed declared dependencies are usable by the application at a specific time according to the scope we defined for these.
The scope is a central concept about how a dependency will be visible for the project.
The default scope is compile. That is the most commonly needed scope (convention over configuration again).
The compile scope means that the dependency is available in all classpaths of a project.
The scope defines in which classpaths the dependency should be added.
For example do we need it at compile and runtime, or only for tests compilation and execution ?
For example we previously defined Hibernate as a compile dependency as we need it everywhere : source compilation, test compilation, runtime and so for....
But we don't want that testing libraries may be packaged in the application or referenced in the source code. So we specify the test scope for them :
<build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
<dependencies>
</build>
One line answer - basic understanding
Plugin is a tool you use at the execution of your maven build
Dependency means kind of any library which you will use in your code
If you're coming from a front-end background like me, and are familiar with Grunt and npm, think of it like this:
First you would run, say, npm install grunt-contrib-copy --save-dev. This is like maven's <dependency></dependency>. It downloads the files needed to execute a build task.
Then you would configure the task in Gruntfile.js
copy: {
main: {
src: 'src/*',
dest: 'dest/',
},
}
This is like maven's <plugin>/<plugin>. You are telling the build tool what to do with the code downloaded by npm/<dependency></dependency>.
Of course this is not an exact analogy, but close enough to help wrap your head around it.
Plug-ins are used for adding functionalities to Maven itself (like adding eclipse support or SpringBoot support to Maven etc.). Dependencies are needed by your source code to pass any Maven phase (compile or test for example). In case of JUnit since the test code is basically part of your code base and you call JUnit specific commands inside test suites and those commands are not provided by Java SDK therefore JUnit must be present at the time Maven is in the test phase and this is handled by mentioning JUnit as a dependency in your pom.xml file.
In simple words:
Plugins are used to add some additonal features to the software/tools(like Maven). Maven will use the added plugins at the time of building when we use the build command.
Dependecies are used to add some addtional code to your source code, so a dependency will make some extra code (like Classes in Java) in the form of library available for your source code.
Maven at its heart is a plugin execution framework -- as per formal and standard compact definition. To make it more clear, the commands you use like maven-install/clean/compile/build etc for creating/executing jars, which we sometimes manually run too. So, the things which you want to run (or configure or execute) you basically put them in dependency tag of mavens pom and the answer so as to who will run these dependencies (required for environment setup) be the plugins.
javac (compiler) dependency.java (dependency)
A plugin is an extension to Maven, something used to produce your artifact (maven-jar-plugin for an example, is used to, you guess it, make a jar out of your compiled classes and resources).
A dependency is a library that is needed by the application you are building, at compile and/or test and/or runtime time.

Maven: skip test but still fails on surefire

I dont know if this is a question or suggestion. But I am going to ask it as a question cos may be i am doing something wrong.
My problem was that I wanted to skip tests in maven build, In eclipse plugin I checked the Skip Test option in configuration when running maven. It was still failing on the Test surefire plugin as it couldn't download the version 2.4.3 (even though my previous maven project used a 2.7.2 and it was already there in my repo) So i tried with skipping tests and it still failed.
I configured my POM to use the 2.7.3 plugin of surefire which i already had and it went forward only to say Skipping Tests. Now, my confusion is that when it was already going to SKIP the test part why bother going into the download and confirming if the plugin for surefire is there or not. Just Skip it I say..
well, Is that the normal behavior of maven that when you skip something the plugin is still downloaded as if you are going to use it. Or was I doing it wrongly that made it download it.
May be because there was something new called "Effective POM" and it contained a listing of surefire plugin 2.4.2 in the plugin management area, when i imported my maven project in eclipse using the m2eclipse and i couldnt edit the Effective POM. I had not seen this before in the NetBeans when making the maven project.
In order to work i added an unnecessary surefire plugin entry in my build profile and skipped the tests there as well and added the version that I had in my repo already. I only did this so that my project can be built under eclipse as well. other wise my project works in NetBeans and simple command line without any issues.
Any comments!!
I think maven should be able to see first the SKIP part and then proceed into the usage of the plugin.
Syed..
Based on what you mentioned you didn't understand the difference between using a plugin and configuring the plugin. In this case you are using the plugin (it's in your build area or as you already figured out coming via super-pom). Furthermore you are trying to skip the tests despite the fact that maven-surefire-plugin in version 2.7.3 does not exist.
The configuration parameter skip will not execute the tests as well as not compile them. If you wan't just ignore the tests for a limited time you can use the "skipTest" parameter which in contradiction to skip will continue to compile the tests.
I would recommend to use a pluginManagement section of your project or your parent pom to define the version of the maven-surefire-plugin (which in the meantime exists in version 2.12)...
The following snippet add the pluginManagement part to a pom which controls which version of the maven-surefire plugin will be used.
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
..
</build>
After you inserted that into your project pom the output effective pom should give you the version...otherwise you might need to update the project configuration first.
Compiling and running tests is part of the default lifecycle of maven. Since maven uses surefire to do run tests, it needs to download surefire. skipTests is not a maven configuration, but a surefire plugin configuration. The plugin determines that maven needs to skip tests.
As for 2.4.3 of surefire plugin, it is a valid version, but will work with 2.0.6 version of maven. Most likely you are using a newer maven, but, for some reason have the super pom of the older maven version on your system.
skipTest doesn't tell maven to skip the test lifecycle, it tells the surefire plugin not to run them. The plugin is still part of the lifecycle (it just does nothing when it's called). Hence your error.
If you want to NOT have surefire at all, you need to define your own packaging (since surefire is part of the standard jar packaging lifecycle) - which is a lot more work than just choosing a version of surefire that works for you (add a section with the right in your section).

Resources