Avoid inheritance of plugins configurations by external modules - maven

Suppose I have the three following maven modules :
parent
heir (submodule of parent, parent is its parent)
extern (other project, parent is its parent)
I would like to configure plugins only for parent and its submodules (parent and heir in my example) without any side effect for external projects (extern in this case).
parent defines a plugin in pluginManagement, for example :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>hello, heir</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>echo</executable>
<arguments>
<argument>Hello, heir!</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
Unfortunately, this plugin configuration will have a side effect on extern.
See, if extern defines the following, the above configuration will apply to him :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
...
</plugin>
Now, how can change my project structure or pom configuration so that :
I can build my whole project from a single command on one pom
I can deploy my whole project from a single command on one pom
I can define plugins for internal use only (parent pom and its submodules) / An external project will not inherit from these plugins
Said plugins are still inherited from internal plugins
?

You need to change the hierarchy to
external-parent
parent
submodules

Related

How to trigger a specific execution of a Maven plugin?

I am trying to figure out whether it is possible to define executions of a Maven plugin in a <pluginManagement> section of a parent pom and pick a specific execution, and only that one, in a child project.
To be more specific, I have several multi-module projects that inherit from our company-wide parent pom. In the <pluginManagement> section of the parent pom, I have several executions of maven-resources-plugin using the copy-resources goal, all bound to phase validate but using different configurations:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<inherited>true</inherited>
<executions>
<execution>
<id>copy-codedeploy</id>
<phase>validate</phase>
...
</execution>
<execution>
<id>copy-settings</id>
<phase>validate</phase>
...
</execution>
<execution>
<id>copy-logback</id>
<phase>validate</phase>
...
</execution>
</executions>
<plugin>
After experimenting many hours on a child project, I would like to:
Avoid having needless executions of copy-logback in all modules, which happens when I define execution copy-logback in the parent POM and has the drawback of creating the destination folder hierarchy in all modules.
Avoid, in case that execution is not defined in the parent POM, defining it in multiple cloned copies in all modules where it is needed.
An example child project has these modules, where the first one is the only module where copy-logback is really needed:
webapp
rest
services
persistence
The best I have arrived at now is to leave common executions in the parent POM, which gives me item #1 in the first list above, but still leaves me cloning the exact same plugin configuration in multiple modules. The configuration that I'm cloning is this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<!-- Copy logback.xml from the parent to the main resources folder, filtering the application name used in log file names. -->
<execution>
<id>copy-logback-file</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/src/main/resources</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/../logback-templates</directory>
<filtering>true</filtering>
<includes>
<include>logback.xml</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
This unfortunately diminishes the usefulness of a <pluginManagement> section in the parent POM as the identical configuration cannot be defined only once. I have to define it in each module of our Portfolio that uses logback, which amounts to tens of times.
To solve my duplication problem, I am thinking that maybe, it's possible to define an execution of a plugin that can be selectively triggered where it's needed. Is it possible?
You can add a skip parameter to the configuration of each execution like:
<skip>${copy.logback.skip}</skip>
And then you can choose in each module whether to use or skip the execution by setting the property <copy.logback.skip> to true or false.

pluginManagement interferes with shade plugin

Just started with Maven for real; got a big surprise right away.
I understand (or I think I do) the concept of fat jar/uberjars. Package your code with all the dependencies, etc. maven-shade-plugin, found docs, some example, checked that it works. Now adding it to my POC project, which came from the maven-archetype-quickstart - what could possibly go wrong, eh?
To put it short, quickstart arrange the the following way:
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
...
So I just threw in a plugin for shading, ready to call it a day:
<!-- Maven Shade Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Not so fast. First, I noticed that mvn clean package didn't mention maven-shade-plugin being executed (like the working example did). Hours of searching followed, and I was staring the "root cause" in the face - <pluginManagement>, offered by quickstart archetype, was it - somehow. Removing that tag magically allowed maven.shade.plugin to do its job. Otherwise, nope.
(Replica: https://github.com/alexakarpov/shade-me
unshade is the bad branch, master is good).
Talk about violation of the Principle of Least Surprise, eh =)
Can someone explain what's going on? The comment in generated pom mentioned something about parent pom, but I'm not doing anything with multi-pom setup yet..
<pluginManagement> role is described in Maven documentation :
Plugin Management contains plugin elements in much the same way [than plugins], except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one.
Its goal here in the project generated by the archetype is to set specified versions of default plugins (maven-clean-plugin, maven-jar-plugin, ...). Note that these default plugins do not appear in your POM <plugins> section, but they are declared implicitly (you can check it by running mvn help:effective-pom).
But adding a plugin to <pluginManagement> section does not make your project invoke that plugin. Here, you can just set configuration and the version of the plugin you want to use. To invoke the plugin, you should absolutely declare it in <plugins> section.
In some projects (most of time multi-module projects), you could see the plugin and its configuration declared in <pluginManagement> of parent POM, and then referenced on <plugins> section of modules needing invocation of that plugin : thus, you do not have to repeat the same configuration on each module.
<pluginManagement> is mostly used if you want to use POM inheritance. Otherwise, on simple projects, you can just declare them in <plugins> section. I've also seen some projects defining all configuration in <pluginManagement>, just to make <plugins> section shorter and more readable, like the following example. It's just a matter of taste.
<build>
<!-- pluginManagement section : set versions and configurations -->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<!-- plugins section : plugins that are invoked when building the project -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>
You can also read more on StackOverflow : Maven : What is pluginManagement?

Maven multi module and plugin calls

my multi module project has the following structure:
parent
module 1 <-- inherits from parent via <relativePath>../parent/pom.xml</relativePath>
module 2 <-- inherits from parent via <relativePath>../parent/pom.xml</relativePath>
aggregator <-- aggregates modules with <modules><module>
The aggregator calls the following plugin:
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>some path</destFile>
</configuration>
</execution>
</executions>
<configuration>
<append>true</append>
</configuration>
</plugin>
</plugins>
</build>
The plugin is called for the aggregator, but i want to call it for all modules (1 and 2).
I know that i can change the parent pom, but i want to keep it clean (that change is part of a bigger implementation).
Is it possible to configure the plugin in such a way, that its called for all modules (just like being placed in parent pom)?
In short: No.
The only way for a module to get a plugin in a lifecycle not defined in its own POM is by inheriting the configuration from its parent.
You should really consider merging parent and aggregator into a single project, i.e. making the aggegrator also the parent. It is much cleaner that way.

Maven plugin dependency - using the source plugin in all my poms

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

getting exec-maven-plugin to execute a class in a dependency

I have two individual maven projects named Utilities and Campaigns. My utilities project has dependencies in it. The Campaigns project needs to execute the main method inside a class within Utilities. To accomplish this, I have been using the exec-maven-plugin. Using this plugin, I'm able to execute the main method of the dependency (Utilities) from my Campaigns pom file. However, transitive dependencies from Utilities don't seem to resolve when I execute the method. I can get around this by adding the same dependencies to both pom files, but if possible I'd like to avoid this redundancy and just inherit from Utilities. I've included the plugin portion of my Campaign pom file below. This is a little confusing, but is there a way I can get around this without having to define the same dependencies? Without having to list the dependencies in the plugin section?
The main method is found in com.sample.generics.Login.java.
Campaign.pom
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.sample.generics.Login</mainClass>
<classpathScope>test</classpathScope>
<arguments>
<argument>${resourcesDir}</argument>
<argument>${settingsFile}</argument>
</arguments>
<includeProjectDependencies>true</includeProjectDependencies>
</configuration>
</plugin>

Resources