So, I'm trying to use the latest version of some plugins. Earlier I've used the prerequisites-tag but lots of resources (example) say that it should be considered deprecated and that the maven-enforcer-plugin should be used instead.
this is my configuration:
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>enforce-maven-3</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.0.4</version>
</requireMavenVersion>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
However, when I run mvn versions:display-plugin-updates I still get this text:
[ERROR] Project does not define required minimum version of Maven.
[ERROR] Update the pom.xml to contain
[ERROR] <prerequisites>
[ERROR] <maven>3.0</maven>
[ERROR] </prerequisites>
[INFO]
[INFO] Require Maven 2.0.6 to use the following plugin updates:
[INFO] maven-jar-plugin ................................................ 2.4
[INFO] maven-shade-plugin ............................................ 1.7.1
[INFO]
[INFO] Require Maven 2.2.1 to use the following plugin updates:
[INFO] maven-jar-plugin ................................................ 2.6
[INFO]
[INFO] Require Maven 3.0 to use the following plugin updates:
[INFO] maven-shade-plugin .............................................. 2.3
Using the prerequisites-tag instead works.
It seems like this issue has been reported here (credits go to Aleksandr M for finding this).
Apparently, the display-dependency-updates goal relies on the prerequisites element to find out the Maven version required by the current project and totally ignores the enforcer-plugin, even though the prerequisites-tag should not be used normally, it is required in order to get the dependency plugin to behave as expected.
To avoid this message I use last version of versions-maven-plugin
mvn org.codehaus.mojo:versions-maven-plugin:2.7:display-plugin-updates
Note that it still requires either use of maven-enforcer-plugin for all but maven-plugin projects, or use of prerequisites tag for projects with maven-plugin packaging.
The prerequisites is deprecated for Maven 3.X:
http://jira.codehaus.org/browse/MNG-4840
http://jira.codehaus.org/browse/MNG-5297
Furthermore if you call
mvn versions:display-plugin-updates
you are not starting a life cycle whereas the configuration of your maven-enforcer-plugin is bound to the life cycle.
Furthermore you should pin all versions of the plugins you are using in your build.
And one very important things (excerpt from the FAQ):
The prerequisites tag was designed to be used by tools like plugins.
It will work for regular projects, but it isn't inherited to their
children. If it is set in a parent reactor, then Maven will do the
check. However if one of the children are built, the check is not
performed. The enforcer plugin is designed to allow centralized
control over the build environment from a single "super-pom", and to
allow greater flexibility in version specification by supporting
ranges.
This means only if your developing plugins the prerequisites does make a limited sense better to use the maven-enforcer-plugin path. For usual development project use the maven-enforcer-plugin configuration way to force particular Maven versions.
To stay informed about plugin update i can recommend to subscribe to the Announcment mailing list or if you like to get a good overview see the plugins page.
Related
I'm building a Java Camel project using Maven 3.3.9 and Camel 2.19.5, everything compiles, but on validation Maven fails with the error below. Looks like Spring boot is trying to auto-configure something. The project is not a typical Springboot app, it's a custom Maven plugin that happens to depend on Camel. My suspicion is Maven's expecting to find main() in the code but it does not exist since the project has no runnable main(). Anyway, that's what I think, it's a nasty issue I'll tell ya that.
[INFO] BUILD FAILURE
[INFO] ----------------------------------------------------
[INFO] Total time: 10.344 s
[INFO] Finished at: 2018-06-22T16:13:41-04:00
[INFO] Final Memory: 39M/622M
[INFO] ----------------------------------------------------
[ERROR] Failed to execute goal
org.apache.camel:camel-package-maven-plugin:2.19.5:
prepare-spring-boot-auto-configuration
(validate) on project ofi-salesforce-maven-plugin:
Execution validate of goal org.apache.camel:camel-package-maven-plugin:2.19.5:
prepare-spring-boot-auto-configuration
failed: Cannot find Apache Camel project root directory
Figured it out; the code was previously using Camel 2.15.1, but after upgrading to Camel 2.19.1 we failed to consider Maven build changes. Since our code is branched from Camel Salesforce Maven plugin, the pom for that project now includes camel-package-maven-plugin, which we failed to include in our pom. The plugin skips validation phase, and that's where the error was happening, makes sense.
<plugin>
<groupId>org.apache.camel</groupId>
<artifactId>camel-package-maven-plugin</artifactId>
<executions>
<execution>
<id>prepare</id>
<phase>none</phase>
</execution>
<execution>
<id>validate</id>
<phase>none</phase>
</execution>
<execution>
<id>readme</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
I'm using this Github project to get exposed to the new modular features in Java 9. I would like to add dependencies to the project and be able to build a native image. However, when I try to add a new dependency to the pom.xml, and add the requires statement to the module-info.java, I get a the following error from the maven-jlink-plugin:
Error: module-info.class not found for joda.time module
I'm trying to use this as a proof of concept that I can deploy images using the new linking phase, but naturally I need to be able to have external dependencies and I need to use maven (work constraint).
Changes to mod-jar/pom.xml
...
<dependencies>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
</dependencies>
...
mod-jar/module-info.java
module com.soebes.nine.jar {
requires java.base;
requires joda.time;
exports com.soebes.example.nine.jar;
}
Logs:
[INFO] --- maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) # mod-jlink ---
[INFO] Toolchain in maven-jlink-plugin: jlink [ /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jlink ]
[INFO] The following dependencies will be linked into the runtime image:
[INFO] -> module: com.soebes.nine.one ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-1/target/jmods/com.soebes.nine.one.jmod )
[INFO] -> module: com.soebes.nine.two ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-2/target/jmods/com.soebes.nine.two.jmod )
[INFO] -> module: com.soebes.nine.jar ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-jar/target/com.soebes.nine.jar-1.0-SNAPSHOT.jar )
[INFO] -> module: joda.time ( /Users/sebastianrestrepo/.m2/repository/joda-time/joda-time/2.9.9/joda-time-2.9.9.jar )
[ERROR]
Error: module-info.class not found for joda.time module
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] parent ............................................. SUCCESS [ 1.460 s]
[INFO] com.soebes.nine.one ................................ SUCCESS [ 2.022 s]
[INFO] com.soebes.nine.two ................................ SUCCESS [ 1.392 s]
[INFO] com.soebes.nine.jar ................................ SUCCESS [ 1.388 s]
[INFO] mod-jlink .......................................... FAILURE [ 1.061 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.911 s
[INFO] Finished at: 2017-11-03T15:27:35-04:00
[INFO] Final Memory: 26M/981M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) on project mod-jlink:
I would really appreciate any help. Thanks.
This has not much to do with the plugin I believe. Module joda.time in your case seems to be an automatic module.
The jlink tool does not support linking of automatic modules because they can rely on the arbitrary content of the classpath, which goes against the idea of a self-contained Java runtime.
So there are two ways to fix this probably :-
(you don't own the jar) Temporarily go ahead create a module-info.java[you could use jdeps tool for it] and update the jar[using jar tool] with the corresponding compiled class as in projects under Java 9.
(you own the dependency) Permanently migrate the jar to Java 9 itself, where it would consist of the module-info.class by itself after being compiled and packaged.
You could use the ModiTect Maven plug-in to add a module descriptor to the JAR and create a modular runtime image with that module.
Disclaimer: I'm the author of ModiTect.
Let me try to explain the technical background on this a little bit:
joda-time in the version 2.9.9 as given in the question is a non-modular jar it does not contain a module-info.class and it does not declare itself as an automatic module by using a Automatic-Module-Name: in its META-INF/MANIFEST.MF
Classes in a real module can not call classes on the classpath thus you can not use the "requires jode.time" in your module-info with that version.
Automatic Modules can use classes on the ClassPath. In order to use Classes from an non-modular jar in a real module you can use a wrapper which itself is an automatic module.
By the time now there exists a version 2.10.1 of joda-time which is an automatic module and declares "Automatic-Module-Name: org.joda.time" thus you can use an "requires org.joda.time" in your real module with that new version.
Now the new jlink tool can not operate directly with non-modular jars or automatic jars and the maven-jlink plugin currently is basically just a maven wrapper around the jlink tool translating its configuration parameters into arguments for the jlink tool.
In order to create a custom Java Runtime for projects using mixed maven dependencies with real modules, automatic modules and non-modular jars you have to know all system module dependencies of your real-modules, automatic-modules and non-modular jars and than use a --add-modules parameter to jlink with these.
To collect the system module dependencies you can use the new jdeps tool with either the --print-module-deps or --list-deps parameter depending on the actual JDK Version being used.
If you are using maven for your project you can automate that task by creating or using a maven plugin that does this for you.
I had a similar problem in one of my projects. First, I tried the moditect-maven-plugin, which worked great! However, with this plugin you have to configure each dependency that is missing a module descriptor separately. If you have many dependencies missing a module descriptor, this can get cumbersome.
Therefore, I decided to develop a new maven plugin, the jigsaw-maven-plugin (see https://github.com/ghackenberg/jigsaw-maven-plugin). The plugin provides three goals for patching all unnamed modules (see Step 3) as well as linking and packaging these modules (see Steps 4 and 5).
Before patching, linking, and packaging, you need to build the project JAR (see Step 1) in and copy the project dependencies (see Step 2) to a common location (e.g. ${project.build.directory}/modules). Maybe you can use the following build plugin configurations to get started (see GitHub page for more details):
Step 1: Build archive
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
</configuration>
</plugin>
Step 2: Copy dependencies
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Step 3: Patch all unnamed modules
Search for JARs in modulePath missing a module descriptor, generate missing module descriptors using jdeps and javac, and add them to respective JARs using java.util.zip.
<plugin>
<groupId>io.github.ghackenberg</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>patch</goal>
</goals>
<configuration>
<modulePath>${project.build.directory}/modules</modulePath>
</configuration>
</execution>
</executions>
</plugin>
Step 4: Link modules
Link modules using jlink.
<plugin>
<groupId>io.github.ghackenberg</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>link</goal>
</goals>
<configuration>
<modulePath>${project.build.directory}/modules</modulePath>
<module>your.module.name</module>
<output>${project.build.directory}/image</output>
</configuration>
</execution>
</executions>
</plugin>
Step 5: Package modules
Package modules using jpackage.
<plugin>
<groupId>io.github.ghackenberg</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>package</goal>
</goals>
<configuration>
<modulePath>${project.build.directory}/modules</modulePath>
<runtimeImage>${project.build.directory}/image</runtimeImage>
<mainClass>your.module.name/your.package.Main</mainClass>
</configuration>
</execution>
</executions>
</plugin>
I have a Maven Scala project that will be deployed on some container and therefore mark several of the dependencies with scope provided meaning those dependencies will be used for compiling but not taken into account for transitive resolution as they are "provided at runtime". However, when I run the following command, it produces the intended jar with dependencies but also including those dependencies that were marked as provided.
mvn clean install assembly:assembly -DdescriptorId=jar-with-dependencies -DskipTests
I tried existing answers to this problem e.g. Excluding “provided” dependencies from Maven assembly but for some reason produces an incorrect choice of dependencies and even missing the main code. In this OP I'd like to find a cleaner, more up to date solution to this problem ... is there one?
You may be better off with a different maven plugin. See Difference between maven plugins ( assembly-plugins , jar-plugins , shaded-plugins. Shade would probably suit you best in this case. What you are looking to create is referred to an uber-jar.
Regarding Shade, from the Maven website:
This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.
The goals for the Shade Plugin are bound to the package phase in the build lifecycle.
Configuring Your Shade Plugin:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
Note that the default implementation replaces your project's artifact with the shade version. Need both? Look here: Attaching the Shaded Artifact
Merging several jars at once is not necessarily utter simplicity and so Shade has the concept of Resource Transformers (link also has more samples).
Aggregating classes/resources from several artifacts into one uber JAR is straight forward as long as there is no overlap. Otherwise, some kind of logic to merge resources from several JARs is required. This is where resource transformers kick in.
The project site is actually quite good. There are lots of varied examples.
One of my projects used the maven-pmd-plugin and I have found that I receive different results when using Maven 3.0.5 and Maven 3.2.1. All other variables (Java version, OS version, project configuration). I've also tried Maven 3.1.1
I'm running
mvn clean pmd:pmd
on the command line
In Maven 3.0.5, I get one warning:
<violation beginline="44" endline="307" begincolumn="8" endcolumn="1" rule="MoreThanOneLogger" ruleset="Java Logging" package="com.adobe.acs.commons.logging.impl" externalInfoUrl="${pmd.website.baseurl}/rules/java/logging-java.html#MoreThanOneLogger" priority="2">
Class contains more than one logger.
</violation>
In Maven 3.2.1 (and 3.1.1), I get zero warnings.
I also tried removing my custom rulset and now have the maven-pmd-plugin configured like this:
<plugin>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.1</version>
<configuration>
<linkXRef>false</linkXRef>
<rulesets>
<ruleset>/rulesets/java/logging-java.xml</ruleset>
</rulesets>
<targetJdk>1.6</targetJdk>
</configuration>
</plugin>
With the same result.
Knowing the wider context of your issue helped me to arrive at the solution without too much discussion.
There is a difference in the graph of implicit dependencies between the various maven versions, as in the ones that come along with maven as baked in defaults. I am able to reproduce this issue locally, and when I add the -X switch for debug mode, and run a diff for mvn clean pmd:pmd pmd:check -X on both maven versions, I see the following import in the 3.2.1 output, which I thought was a possible candidate for follow-up, since it has to do not only with the kind of logging that the rule checks for, but also because I happen to know you are using slf4j:
[DEBUG] Imported: org.slf4j.* < plexus.core
It appears that SLF4j was added to plexus.core, which may mean that the slf4j api is available to all plugin classpaths now, whereas before it would require that the plugin imported the library in its own dependencies.
I went to see what the PMD MoreThanOneLoggerRule is looking up, and it turns out it only looks for Log4j loggers and JCL loggers by resolved type, and anything named "Logger" if it can't resolve the type:
http://pmd.sourceforge.net/pmd-5.1.1/xref/net/sourceforge/pmd/lang/java/rule/logging/MoreThanOneLoggerRule.html
The solution appears to be to add the slf4j API right in the pmd plugin dependencies, as in:
<plugin>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.1</version>
<configuration>
<linkXRef>false</linkXRef>
<rulesets>
<ruleset>/rulesets/java/logging-java.xml</ruleset>
</rulesets>
<targetJdk>1.6</targetJdk>
</configuration>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
</plugin>
This puts org.slf4j.Logger on the PMD classpath, so that it is able to resolve the type during analysis. Since it is neither a Log4j Logger or JCL Logger, it no longer cares about having more than one of them.
I have created a maven android project using this archetype. I want to integrate mirah source files inside my project. So I added the plugin mentioned here to my pom.xml. I setup the configuration section for the plugin to point the source directory to src/main/mirah.
But when I run mvn compile it only compiles the sources inside src/main/java. I have tried running it with mvn -X compile to try and debug the issue, but I can't find anything related to mirah or the mirah-maven-plugin there.
Using the archetype it created two projects - project and project-it (tests) , there is a pom.xml in the root directory as well as a pom.xml in project and project-it directories. I have tried the above configurations in both the root directory as well as in project's pom.xml.
I have come across this question related to using the build-helper plugin but I don't know if it will help in my case. Since my mirah plugin isn't getting called at all.
Is this the right way to do what I'm trying to do? Any help on the setup, or pointer to how to troubleshoot this would be much appreciated.
The relevant bit of my pom.xml
<plugin>
<groupId>org.mirah.maven</groupId>
<artifactId>maven-mirah-plugin</artifactId>
<version>1.0</version>
<configuration>
<sourceDirectory>src/main/mirah</sourceDirectory>
<outputDirectory>target/classes</outputDirectory>
<bytecode>true</bytecode>
<verbose>false</verbose>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals><goal>compile</goal></goals>
</execution>
</executions>
</plugin>
Edited as per answer below.
I have added the source directory using the build-helper plugin and I'm able to get the mirah sources to compile using mvn org.mirah.maven:maven-mirah-plugin:1.0:compile from the answer below. But mvn compile still only compiles the sources in src/main/java and not src/main/mirah.
For anyone interested in the output of mvn -X compile here is the pastie.
This page https://github.com/calavera/maven-mirah-plugin#readme says that the mirah plugin extends the default compiler plugin. So this would suggest that the build helper plugin would work for multiple source directories, if it works for the default compiler plugin.
Looking at the mirah plugin, you probably don't need to specify sourceDirectory and outputDirectory yourself, as it seems you're using the defaults.
The -X switch won't have any impact on the mirah plugin directly, as it doesn't do any tracing itself (above what the default compiler plugin does).
Can you show your -X output anyway to show that the mirah plugin isn't invoked?
Alternatively, you could build the mirah plugin yourself and add tracing. It doesn't seem a complicated plugin.
What happens when you try and invoke the plugin directly? E.g.
mvn org.mirah.maven:maven-mirah-plugin:1.0:compile
EDIT:
Tried it myself and this works for me (by 'works' I mean the plugin gets invoked - my build actually fails).
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>temp</groupId>
<artifactId>temp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.mirah.maven</groupId>
<artifactId>maven-mirah-plugin</artifactId>
<version>1.0</version>
<configuration>
<bytecode>true</bytecode>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
With this output:
D:\dev\workspaces\3.6\temp>mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Unnamed - temp:temp:jar:0.0.1-SNAPSHOT
[INFO] task-segment: [compile]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [mirah:compile {execution: default}]
[INFO] No sources to compile
Parsing...
D:\dev\workspaces\3.6\temp\src\main\mirah/test.mirah
Inferring types...
* [Mirah::Typer] Learned local type under #<Mirah::AST::StaticScope:0xbc5245> : a = Type(int)
... ETC ...
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Unknown error - Unknown Error (20047) - D:\dev\workspaces\3.6\temp\target\classes\D:
I don't know what the error means as I'm not a mirah user.