I've defined a Maven plugin with multiple goals. Currently users run my plugin as follows:
<plugin>
<groupId>myGroupId</groupId>
<artifactId>myArtifactId</artifactId>
<version>someVersion</version>
<executions>
<execution>
<goals>
<goal>myGoal</goal>
</goals>
</execution>
</executions>
</plugin>
but I've seen other plugins, like maven-compiler-plugin and Flyway, that don't require specifying an execution: https://flywaydb.org/getstarted/java
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>5.2.4</version>
<configuration>
<url>jdbc:h2:file:./target/foobar</url>
<user>sa</user>
<locations>
<location>classpath:db/migration</location>
</locations>
</configuration>
</plugin>
How do I specify the goal that should run by default when users exclude the <executions> block?
AFAIK, there are not default goals for Maven plugins.
You can configure a plugin without adding a goal. But this does not execute the plugin.
The plugin must be either executed explicitly on command line (like flyway:migrate) or is executed automatically through the lifecycle (like compile:compile or jar:jar).
I assume you are using the Java5 Annotations to mark your plugin as available mojo? (and not the javadoc way of living).
The #Mojo annotation has a defaultPhase attribute.
Once a user adds the plugin into the build these defaults (if set) will be used.
The Flyway Migrate Mojo does it this way too.
The compiler plugin is a bit of a bad example, as it is part of the default plugin bindings of the maven life-cycle itself. So the phase itself will know what mojo to run.
These are the docs for the maven plugin api, the one for using annotations is nearby.
If it is not your plugin, you can put the configs you want into a parent pom into the pluginManagement section.
I am reading sonatype's tutorial on multimodule projects and I see that in submodule they use the <pluginManagement> configuration like this:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
This confuses me as I thought that <pluginManagement> is to be used in parent POM to provide common plugin configuration for submodules. What are the reasons for using plugin managment in children poms ?
Most of the time <pluginManagement> is used in parent pom files.
It configures plugins. But makes them not active part of the build. Therefor you need to add them to the <plugins> part of the Maven pom file. Most not done in parent pom files, but done in the (sub) modules, using / refering to that (parent) pom.
I think this is special to the use of the surefire plugin.
Since you execute the plugin with mvn test the surefire plugin will be executed with the configuration specified in the pluginManagement block. Other plugins are not executed directly but by binding them to another lifecycle phase and thus must be specified in the plugin block.
See the usage page of the surefire plugin.
I know Maven compiler plugin by DEFAULT is bind to :
compile
test compile
life cycles, in general without specifying addition configuration, we don't have to
explicitly define it in our POM, but I still seen experienced developer putting things like
this in their POM, e.g
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
I wander what's the point? and why is he doing this?
For the shade plugin, he is probably using POM inheritance. Look in the parent POM hierarchy for a pluginManagement section, there is probably shade plugin configuration there that he is pulling into this module.
For the compiler plugin, I do not know. You are correct, for jar/war/ear/ejb projects Maven will pull in the compiler config automatically, even if he has defined specific configuration in a parent POM's pluginManagement section.
If they put such things in their pom's they don't understand Maven. You should define the version of the plugins your are using in your build. This is done by:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin<artifactId>
<version>3.1</version>
<configuration>
<target>1.6</target>
<source>1.6</source>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin<artifactId>
<version>2.3</version>
</plugin>
</plugins>
</pluginManagement>
</build>
This should be usually located into a pom file known under Company POM which defines versions of plugins for projects within a company.
Furthermore based on the life-cycle definition in Maven the Maven Super POM which contains the default bindings there you could see that particular plugins versions are defined.This means if you upgrade your Maven version you start using different plugin versions which is fact not the best related to build reproducibility. So the best practice is to define all used plugins like here as an example.. Based on the definition you shouldn't need to mention anything in your build-tag area if you have a defined packaging type (This is one of those Convention Over Configuration paradigm hints).
I would like to configure the use of the maven source plugin for all our projects. The way our projects are currently configured we have a parent pom that is inherited by all the projects. So, in order for all projects to use the maven source plugin, I did the following:
Defined the maven source plugin under build -> plugin management in the parent pom
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
In my project pom (the child pom), I have included the source plugin under build -> plugins
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
Could someone please tell me if this is the best way to configure this? Is there any way you can avoid specifying the source plugin in the child pom?
This is the best way.
To avoid having to add the plugin declaration in the child pom you could add it to the build/plugins section in the parent. The problem with that however is that EVERY child gets that invocation added even if it does not make sense if e.g. the child is a pom or ear packaging. You should therefore not do this..
I have a set of projects which all need to run the same series of Maven plugin executions during their builds. I'd like to avoid re-declaring all of this configuration in every project, so I made them all inherit from a parent pom "template" project which only contains those plugin executions (8 different mojos). But I want those plugin executions to only run on the child projects and not on the parent project during Maven builds.
I've tried to accomplish this four different ways, each with a side-effect I don't like.
Declare the plugin executions in the parent pom's build/plugins element and use properties-maven-plugin to turn on the skip properties on other plugins in the parent project. This didn't work because one of the plugin goals (maven-dependency-plugin:build-classpath) doesn't have a skip property.
Declare the plugin executions in the parent pom's build/pluginManagement element. Unfortunately this requires me to redeclare each of the eight plugins in the build/plugins element of every child project's pom like:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
...
This is too repetitive, and problematic if I ever need to change the plugins in the template pom.
Declare the plugin executions in a profile in the parent pom which is activated by the lack of a nobuild.txt file (which does exist in the parent pom, so the plugins don't execute there):
<profiles>
<profile>
<activation>
<file>
<missing>nobuild.txt</missing>
</file>
</activation>
<build>
....
</build>
</profile>
</profiles>
This works for the most part, except that the file path in the missing element seems to be based on the current working directory instead of the project basedir. This breaks some of the multimodule builds I'd like to be able to do. Edit: to clarify, the parent "template" project is actually itself a module in a multimodule project, and the build breaks when I try, for instance, to do a mvn install on the root. The project structure looks like:
+ job
|- job-core
|- job-template
|- job1 inherits from job-template
|- job2 inherits from job-template
Set up a custom lifecycle and packaging. This seems to allow me to bind plugins to lifecycle phases, but not specify any configuration.
So, is there another way to specify a bunch of Maven plugin executions that can be reused across several projects (with minimal repetition in each of those projects' poms)?
Here's the fifth way. I think it has minimum drawbacks: no profiles, no custom lifecycle, no declarations in child POMs, no 'skip' requirement for plugins.
Copied it from https://stackoverflow.com/a/14653088/2053580 -- many thanks to end-user!
<build>
<pluginManagement>
<plugins>
<plugin>
<!-- Main declaration and configuration of the plugin -->
<!-- Will be inherited by children -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<!--This must be named-->
<id>checkstyle</id>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<!-- You may also use per-execution configuration block -->
<configuration...>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<!-- This declaration makes sure children get plugin in their lifecycle -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<!-- Configuration won't be propagated to children -->
<inherited>false</inherited>
<executions>
<execution>
<!--This matches and thus overrides execution defined above -->
<id>checkstyle</id>
<!-- Unbind from lifecycle for this POM -->
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
I ended up writing my own plugin which utilizes mojo-executor to invoke other mojos. This allows me to 1) centralize the build configuration and 2) minimize the amount of configuration that gets duplicated in each of the child projects.
(In case you are curious about the reason for all of this: each child project is a job which will be executed from the command line. The build sets up an invoker shell script and attaches it to the build so it gets checked into our artifact repository. A deploy script later pulls these down onto the machine they will run on.)
Relevant parts of the template project's pom:
<project ...>
<parent> ... </parent>
<artifactId>job-template</artifactId>
<packaging>pom</packaging>
<name>job project template</name>
<build>
<pluginManagement>
<plugin>
<groupId>...</groupId>
<artifactId>job-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-sources-step</id>
<goals><goal>job-generate-sources</goal></goals>
</execution>
<execution>
<id>package-step</id>
<goals><goal>job-package</goal></goals>
</execution>
... (a couple more executions) ...
</executions>
</plugin>
</pluginManagement>
</build>
</project>
Had to create a new maven-plugin project (job-maven-plugin). Pom looks like:
<project ...>
<parent> ... </parent>
<artifactId>job-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>job maven executor plugin</name>
<dependencies>
<dependency>
<groupId>org.twdata.maven</groupId>
<artifactId>mojo-executor</artifactId>
<!-- version 1.5 supports Maven 2, while version 2.0 only supports Maven 3 -->
<version>1.5</version>
</dependency>
</dependencies>
</project>
As you can see from the template project, there were multiple mojos in my plugin (one per phase that needed stuff to happen). As an example, the job-package mojo is bound to the package phase and uses the mojo-executor library to run two other mojos (which just attach some build artifacts):
/**
* #goal job-package
* #phase package
*/
public class PackageMojo extends AbstractMojo {
/**
* #parameter expression="${project}"
* #required
* #readonly
*/
protected MavenProject project;
/**
* #parameter expression="${session}"
* #required
* #readonly
*/
protected MavenSession session;
/**
* #component
* #required
*/
protected PluginManager pluginManager;
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
ExecutionEnvironment environment = executionEnvironment(project, session, pluginManager);
// Attach script as a build artifact
executeMojo(
plugin(
groupId("org.codehaus.mojo"),
artifactId("build-helper-maven-plugin"),
version("1.7")
),
goal("attach-artifact"),
configuration(
element("artifacts",
element("artifact",
element("file", "${project.build.directory}/script.shl"),
element("type", "shl")
)
)
),
environment
);
// Zip up the jar and script as another build artifact
executeMojo(
plugin(
groupId("org.apache.maven.plugins"),
artifactId("maven-assembly-plugin"),
version("2.3")
),
goal("single"),
configuration(
element("descriptors",
element("descriptor", "${project.build.directory}/job/descriptor.xml")
)
),
environment
);
}
}
Then, in the child projects, I just have to refer to the plugin once. In my opinion, this is greatly preferable over reiterating each of the behind-the-scenes plugins in every child project (which unacceptably increases the coupling between poms). If I want to add a mojo execution to the build procedure in the future, I only have to modify one place and bump a version number. Child project's pom looks like:
<project ...>
<parent>
<groupId> ... </groupId>
<artifactId>job-template</artifactId>
<version> ... </version>
<relativePath>../job-template</relativePath>
</parent>
<artifactId>job-testjob</artifactId>
<name>test job</name>
<build>
<plugins>
<plugin>
<groupId> ... </groupId>
<artifactId>job-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Also, the entire multimodule directory structure now looks like this:
+- job
+- job-core
+- job-maven-plugin
+- job-template
+- job-testjob1 (inherits from job-template)
+- job-testjob2 (inherits from job-template)
In my opinion this solution is not entirely optimal, since I now have plugin configuration embedded in a series of mojos instead of a pom, but it meets my goals for centralizing the configuration and minimizing the duplication among child project poms.
(One last note: I just discovered maven-aggregate-plugin which seems to allow grouping multiple plugin executions in the pom. This might have solved the problem in a slightly more desirable way, but I'm not in the mood to redo the last few hours of work. Might be beneficial to someone else though.)
Personally I would go for solution 2. The repetition is minimal and you should try to avoid profiles if possible to avoid having to start documenting which profiles need to be activated for which projects.
A project should be able to be built correctly by simply doing a mvn (clean) install.
Here's another option I discovered here while looking for solution to the same problem. I'm posting it here because this is already a good collection of options - in the hope that it might help others not spend hours on solving this issue:
Given that the plugin has the option to skip execution, that option could be turned on in the parent pom ( section), with "inherit" flag set to false so that it's not propagated to children:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<inherited>true</inherited>
<configuration>
...
</configuration>
</execution>
</executions>
<!-- Skip plugin execution for parent pom but enable it for all children -->
<configuration>
<skipAssembly>true</skipAssembly>
</configuration>
<inherited>false</inherited>
</plugin>
While I was quite skeptical about this solution when I first read it, it worked for me - at least for the assembly plugin.
One more option: instead of using a "skip" property you can change the phase an execution is bound to a non existent value like never.
This works very nice together with the <inherited>false</inherited> approach suggested by #Timi