How does Maven resolve plugin versions? - maven

I'm reading the docs and still confused as to how Maven is deciding which versions of plugins to download.
For example, consider this simple scenario:
an empty local repository
a default settings.xml
run a simple maven command. for example, mvn archetype:generate for the maven-archetype-quickstart as described in the Maven in 5 Minutes doc.
After running the command, the first thing Maven does is download a bunch of plugins.
Some of the plugins Maven is downloading include:
maven-clean-plugin-2.4.1
maven-install-plugin-2.3.1
maven-deploy-plugin-2.5
Why those versions?
The most recent version of these plugins are:
maven-clean-plugin-2.5
maven-install-plugin-2.5.1
maven-deploy-plugin-2.8.1
I looked at the LATEST version metadata for maven-clean-plugin and it's 2.5
It's not that I necessarily want to force Maven to use different versions of these plugins, I just want to understand WHY it's resolving to those versions.
I'm using Apache Maven 3.0.3

Maven defines 3 lifecycles in META-INF/plexus/components.xml:
1. Default Lifecycle
Default lifecycle are defined without any associated plugin. Plugin bindings for these lifecycles are defined separately for every packaging in META-INF/plexus/default-bindings.xml
e.g. Plugin bindings for jar packaging
<phases>
<process-resources>
org.apache.maven.plugins:maven-resources-plugin:2.6:resources
</process-resources>
<compile>
org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile
</compile>
<process-test-resources>
org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
</process-test-resources>
<test-compile>
org.apache.maven.plugins:maven-compiler-plugin:2.5.1:testCompile
</test-compile>
<test>
org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
</test>
<package>
org.apache.maven.plugins:maven-jar-plugin:2.4:jar
</package>
<install>
org.apache.maven.plugins:maven-install-plugin:2.4:install
</install>
<deploy>
org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
</deploy>
</phases>
2. Clean Lifecycle
clean lifecycle is defined directly with its plugin bindings.
<phases>
<phase>pre-clean</phase>
<phase>clean</phase>
<phase>post-clean</phase>
</phases>
<default-phases>
<clean>
org.apache.maven.plugins:maven-clean-plugin:2.5:clean
</clean>
</default-phases>
3. Site Lifecycle
Site lifecycle is defined directly with its plugin bindings.
<phases>
<phase>pre-site</phase>
<phase>site</phase>
<phase>post-site</phase>
<phase>site-deploy</phase>
</phases>
<default-phases>
<site>
org.apache.maven.plugins:maven-site-plugin:3.3:site
</site>
<site-deploy>
org.apache.maven.plugins:maven-site-plugin:3.3:deploy
</site-deploy>
</default-phases>
If you want to override these default plugin version you can do it from command prompt as follows
mvn org.apache.maven.plugins:maven-clean-plugin:2.0:clean
instead of
mvn clean:clean

Every version of Maven binaries has certain versions of plugin versions hardcoded. That's to make a somewhat reproducible build in the cases when user doesn't provide his own version information. Which you are encouraged to do and once you populate <pluginManagement> section with the plugin versions of your choice, the build will start using it.

It becomes quite clear if you use -X option when building your projects. Please, check my answer in another thread:
https://stackoverflow.com/a/48874533/4470135

Related

"Artifact is not fully assembled" error with maven-invoker-plugin in parallel build

According to the docs, maven-invoker-plugin is "thread-safe and supports parallel builds." However, when I build by multi-module project with -T 1C, I get an error like the following:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-invoker-plugin:1.10:install (integration-test) on project my-archetype: Failed to install project dependencies: MavenProject: com.tavianator:my-archetype:1.6-SNAPSHOT # /home/tavianator/code/Project/my-archetype/pom.xml: Failed to install project artifacts: MavenProject: com.tavianator:my-project:1.6-SNAPSHOT # /home/tavianator/code/Project/my-project/pom.xml: Failed to install artifact: com.tavianator:my-project:jar:1.6-SNAPSHOT: Artifact is not fully assembled: /home/tavianator/code/Project/my-project/target/classes -> [Help 1]
The project layout is like this:
Root
|--Project 1
|--Project 2
|--Archetype (depends on Project 1, scope=test)
The archetype integration tests use the maven-invoker-plugin to install the relevant dependencies (Root and Project 1) to a local repository, then runs the normal archetype integration tests. In parallel builds, Archetype and Project 2 run at the same time. When the maven-invoker-plugin runs, it tries to install Project 2 to the local repo, but Project 2 isn't built yet, hence the error.
But since Project 2 isn't even needed for the tests, I should be able to work around the problem by explicitly installing only the needed dependencies. I don't see how to get the invoker plugin to do that, but is there another plugin I can use?
I reported the maven-invoker-plugin bug here. I have an example project that demonstrates the error here.
I ran into this problem as well, in addition to other problems with the setup suggested in Fast Build Configuration (such as some artifacts being downloaded by the invoked project in every run), and implemented my own solution. Instead of the invoker:install goal, you would use the following:
<plugin>
<groupId>com.github.veithen.invoker</groupId>
<artifactId>resolver-proxy-maven-plugin</artifactId>
<version>0.1</version>
<executions>
<execution>
<goals>
<goal>start</goal>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
Note that there is no need to explicitly configure settings.xml or a dedicated local repository. This is done automatically.
Currently the code in the plugin is experimental. If it turns out to be robust enough, I will submit a patch integrating it into maven-invoker-plugin. More information here.

Wro4j maven plugin - required class is missing

I'm trying to run wro4j maven plugin according to the documentation
I add the plugin to my pom.xml:
<plugin>
<groupId>ro.isdc.wro4j</groupId>
<artifactId>wro4j-maven-plugin</artifactId>
<version>1.5.0</version>
</plugin>
and run the goal:
mvn wro4j:run -Dminimize=true -DtargetGroups=all
However the build fails with error:
org.apache.maven.lifecycle.LifecycleExecutionException: Internal error in the pl
ugin manager executing goal 'ro.isdc.wro4j:wro4j-maven-plugin:1.5.0:run': Unable
to load the mojo 'ro.isdc.wro4j:wro4j-maven-plugin:1.5.0:run' in the plugin 'ro
.isdc.wro4j:wro4j-maven-plugin'. A required class is missing: org/codehaus/plexu
s/util/Scanner
Do you know how to avoid this error?
Since wro4j-1.5.0, the maven 3.0 is required to run the plugin. The reason is a feature called incremental build support which depends on a library which is not available on older version of maven by default.
The issue is on your local environment.
Go to this folder on my windows machine:${user.home}/.m2/repository, then delete everything in this folder. (Well you can keep a copy.)
After deleting, run the Maven command:mvn clean install -U.
See: https://groups.google.com/forum/#!topic/wro4j/ZPSFBQ_5lI8

Maven plugin prefix resolution doesn't seem to work as expected

I've created a MOJO for a specific application need. I've followed maven's guidelines in naming the plugin so that I didn't have to mention the full
mvn groupId:artifactId:version:goal
for executing my plugin(I've named it to match the format ${prefix}-maven-plugin).
I've even included the 'goalPrefix' property in the plugin POM's configuration section. Here's a sniff of what I did to my plugin's POM:
<configuration>
<goalPrefix>${prefix}</goalPrefix>
</configuration>
But I'm still unable to execute my plugin just using mvn ${prefix}:goal since it complains it can't find the plugin in any repository. I've still had to use mvn groupId:artifactId:version:goal Any idea why?
By default, Maven does only recognize plugins with the group IDs org.apache.maven.plugins and org.codehaus.mojo. If your plugin has a different group ID (which should be the case), you need to add this group ID as plugin group to your Maven settings.xml file:
<settings>
...
<pluginGroups>
<pluginGroup>the.groupid.of.my.plugin</pluginGroup>
</pluginGroups>
...
</settings>
Take a look at the Maven Settings Reference for further details.

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).

How to distribute a binary dependency in maven?

I'm trying to convert a project from ant to maven.
The unit tests depend on a third party binary jar, which is not available in any public maven repositories.
How do I make maven handle this situation? I have found two solutions, neither of which are acceptable. First is to use a system dependency; this doesn't work because a) the dependency should only be for the tests, and b) the dependency is not found by eclipse after generating an eclipse project.
Second is to manually install the dependency in a local repository. This seems to be the recommended way. I don't want to do this because I want users to be able to build and test with a simple 'mvn test'. If users have to read a document and copy/paste some shell commands to be able to build and test, then something's wrong.
I suppose it would be OK if maven itself installed the dependency in the local repository as part of the build - is this possible, and if so, how?
Aled.
You may want to look at install:install-file. You can make it execute in the early phase of your project (validate or initialize) via standard means.
On the second thought, if it fails because of missing dependency in the same project, there are couple more options. One is to call ant script via antrun plugin to install artifact.
Or create additional module not dependent on your artifact to be executed prior to main module and have that module install artifact as described earlier.
First of all my way would be using a repository manager such as nexus and installing this dependency to there.
However there is another solution. You can include this 3rd party jar to your project and with test plugin you can configure to include it in classpath such this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.10</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>path/to/additional/resources</additionalClasspathElement>
<additionalClasspathElement>path/to/additional/jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
By the way, I hope that you are aware of that maven is executing surefire plugin in order to run tests by default lifecycle.

Resources