maven2: how to share a plugin configuration between parent and children pom? - maven-2

I'm trying to reduce copy/pasting in our maven pom files.
We have one master pom and many children projects pom inheriting from the master.
I want to share a complex plugin definition looking like:
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<configuration>
<!-- many xml lines here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
<goal>generate-daemons</goal>
<goal>create-repository</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo.appassembler</groupId>
<artifactId>appassembler-booter</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
...
</plugins>
When this plugin definition is in the project pom, packaging is well done.
When definition is moved to parent pom (in or in ), then the packaging is not even started.
Is it possible to share a plugin configuration ? How ?
-- Edit after first answers---
I have tried the following:
- put my XL packaging plugin config in the element of my parent pom
- add this lines in my project pom in the element:
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
</plugin>
...
</plugins>
but it is not working...
What can be wrong with that ?
-- last edit --
I think I get what was the problem:
the plugin re-use declaration should be declared in a profile build.
I done that in an always enabled plugin and now it is working fine.
Thanks a lot.

You could wrap the plugins of the parent in a <pluginManagement> tag.
<build>
<pluginManagement>
<plugins>
<plugin> ... </plugin>
</plugins>
</pluginManagement>
</build>
Children plugins will then inherit the configurations when they declare the plugin in their build tag.

Have you tried using the plugin management feature of Maven? It'll allow you to push that configuration information down to the children pom.xml files from the parent pom.xml:
<build>
<pluginManagement>
<plugins>
<plugin>your_plugin</plugin>
</plugins>
</pluginManagement>
</build>
Now, not all plugins are as well done as those from the org.apache.maven.plugins group. It may be necessary to move your configuration section in between your execution elements.

Related

Maven 3, maven-site-plugin, how to configure reportPlugins in a multi-module project

With Maven 3, the site plugin has changed regarding reporting.
In the maven 2, the reporting section had the an "inherited" element. For example:
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${failsafe.plugin.version}</version>
<configuration>
<useFile>false</useFile>
</configuration>
<inherited>true</inherited>
<reportSets>
<reportSet>
<reports>
<report>report-only</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
Does report plugin inheritance exist in Maven 3? So in maven 3 what is the inheritance behavior for reportPlugins and is there any way to change this behavior like the maven 2 inherited element?
Secondly, does the section have any affect on plugin configurations in the reportPlugins under the site plugin? Or do configurations have to be duplicated in pluginManagement & reportPlugins sections? Does any of this configuration also have to be duplicated in submodules?
At the end of the day I'd like to do something like the following in Maven 3:
<!-- in parent pom -->
<build>
<pluginManagement>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${failsafe.plugin.version}</version>
<configuration>
<useFile>false</useFile>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>report-only</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<!-- no version num or config - specified in pluginManagement section -->
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<reportPlugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<!-- no version num, config, or report set - specified in pluginManagement section -->
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
<!-- in sub module pom -->
<!-- specify nothing - already in parent pom-->
And I would like all of these configurations to be inherited to submodules. Even the reportPlugins section.
Is any/all of this possible with maven 3 currently?
It looks like this may not be completely possible.
Refer to this issue in the maven-site-plugin.
It is supposedly now working just like you wanted back then,
since Maven 3.5, released in 2017.

Configure Maven plugins to stick together

I have parent pom which configures certain plugins
<pluginManagement>
</plugins>
<plugin>
<artifactId>gmaven-plugin</artifactId>
...
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
...
</plugin>
<plugin>
<artifactId>cargo-maven2-plugin</artifactId>
...
</plugin>
</plugins>
</pluginManagement>
And I have tree of poms which are represent integration tests
A-\
a1
a2
B-\
b1
b2
C-\
D-\
d1
d2
In each a,b,d products I do
<build>
<plugins>
<plugin>
<artifactId>gmaven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<artifactId>cargo-maven2-plugin</artifactId>
</plugin>
</plugins>
</build>
The problem is when I will need to add fourth plugin to integration test process for example my custom plugin I will need to move
through all of the integration modules and do manual adding.
You can advice me to remove <pluginManagement> to allow all child just to use them implicitly.
Yes, but in products which are just 'pom' I don't want plugins to do anything: create some resources and put jboss configuration directories.
I wonder is there some kind of
<pluginsBundle>
<groupId>my.group</groupId>
<artifactId>my-integration-test-bundle</artifactId>
<plugins>
<plugin>
<artifactId>gmaven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<artifactId>cargo-maven2-plugin</artifactId>
</plugin>
</plugins>
</pluginsBundle>
To allow me use it just like
<plugin>
<groupId>my.group</groupId>
<artifactId>my-integration-test-bundle</artifactId>
<runOnce>true</runOnce>
</plugin>
I would like to add option like
<runOnce>true</runOnce>
to be able to start application server and deploy target only one time per maven launch.
I don't know of a mechanism that does exactly what you need. Your best bet is to define a parent pom with those plugins defined in the build section, rather than the pluginManagement section. In this case the plugin configuration will always be defined. Adding the configuration to a profile in the parent means you can exercise some control over the activation of those plugins.
One refinement to consider is that you can control activation of a profile by the presence or absence of a file. This way you can define the profile in the parent, but have it deactivated in that project because of the marker file being present in the parent. Child projects would not have the marker file in their source, so the profile would be activated for those projects. You can reverse the behaviour by using missing instead of exists if that makes sense for the majority of projects.
<profile>
<id>build</id>
<activation>
<file>
<missing>src/main/resources/build.marker</missing>
<!-- or if you want to enable the profile when the file does exist:
<exists>src/main/resources/build.marker</exists-->
</file>
</activation>
<build>
</plugins>
<plugin>
<artifactId>gmaven-plugin</artifactId>
...
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
...
</plugin>
<plugin>
<artifactId>cargo-maven2-plugin</artifactId>
...
</plugin>
</plugins>
</build>
</profile>
Alternatively, you could try writing custom plugin with a lifecycle that executes all the required mojos in a forked lifecycle. I recently answered another question with details of how to do this.
Another alternative is to write another plugin that uses Maven shared-io to apply a descriptor
to the pom, that descriptor can define arbitrary configuration that is merged into the pom. Another answer describes how this can be done.
AFAIK, there is no way to declare a bundle of plugins that could be used somewhere else... but there is inheritance.
What about creating a pom with the <plugins> declaration in the <build> section and inheriting from this pom in your integration tests projects? This looks like feasible.

Maven2 - problem with pluginManagement and parent-child relationship

from maven documentation
pluginManagement: is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.
Now : if I have this in my parent POM
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
Some stuff for the children
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
and I run mvn help:effective-pom on the parent project I get what I want, namely the plugins part directly under build (the one doing the work) remains empty.
Now if I do the following :
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
Some stuff for the children
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<inherited>true</inherited>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
mvn help:effective-pom I get again just what I want, the plugins contains just what is declared and the pluginManagement section is ignored.
BUT changing with the following
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
Some stuff for the children
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
<executions>
some stuff for adults only
</execution>
</executions>
</plugin>
</plugins>
</build>
and running mvn help:effective-pom
the stuff from pluginManagement section is added on top of what is declared already. as such :
<build>
<pluginManagement>
...
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
<executions>
Some stuff for the children
</execution>
<executions>
some stuff for adults only
</execution>
</executions>
</plugin>
</plugins>
</build>
Is there a way to exclude the part for children from the parent pom's section ? In effect what I want is for the pluginManagement to behave exactly as the documentation states, that is I want it to apply for children only but not for the project in which it is declared.
As a corrolary, is there a way I can override the parts from the pluginManagement by declaring the plugin in the normal build section of a project ? whatever I try I get that the section is added to executions but I cannot override one that exists already.
EDIT:
I never did find an acceptable solution for this and as such the issue remains open. Closest solution was offered below and is currently the accepted solution for this question until something better comes up. Right now there are three ways to achieve the desired result (modulate plugin behaviour depending on where in the inheritance hierarchy the current POM is):
1 - using profiles, it will work but you must beware that profiles are not inherited, which is somewhat counter intuitive. They are (if activated) applied to the POM where declared and then this generated POM is propagated down. As such the only way to activate the profile for child POM is specifically on the command line (least I did not find another way). Property, file and other means of activation fail to activate the POM because the trigger is not in the POM where the profile is declared.
2 - (this is what I ended up doing) Declare the plugin as not inherited in the parent and re-declare (copy-paste) the tidbit in every child where it is wanted. Not ideal but it is simple and it works.
3 - Split the aggregation nature and parent nature of the parent POM. Then since the part that only applies to the parent is in a different project it is now possible to use pluginManagement as firstly intended. However this means that a new artificial project must be created that does not contribute to the end product but only serves the could system. This is clear case of conceptual bleed. Also this only applies to my specific and is hard to generalize, so I abandoned efforts to try and make this work in favor of the not-pretty but more contained cut and paste patch described in 2.
If anyone coming across this question has a better solution either because of my lack of knowledge of Maven or because the tool evolved to allow this please post the solution here for future reference.
Thank you all for your help :-)
Adding the plugin configuration to pluginManagement means that this configuration will be used if the plugin is declared, but you still need to declare the plugin in the build section of any POM that wants to use it.
The key part that explains this from the section you quoted is:
However, this only configures plugins that are actually referenced within the plugins element in the children
So if you do this in the child pom the configuration from the parent will be applied:
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
</plugins>
</build>
Update: To answer the actual question, the content from the pluginManagement section is always merged with any plugin declaration. To avoid the parent doing this, you can define the pluginManagement section within a profile, and activate that profile on child projects but not the parent. The child projects would then have to declare that profile.
For example:
<profiles>
<profile>
<id>for-children</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
<!--Some stuff for the children-->
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
<!--some stuff for adults only-->
</executions>
</plugin>
</plugins>
</build>
I always used to think that a child POM can inherit a plugin definition from its parent's pluginManagement section and specify only the executions it wants to run from that plugin by referencing them by ID and binding the execution to a phase. As long as the parent definition is in pluginManagement (and not directly in plugins) and is not bound to a phase, only the specific execution (with ID) will be run in that phase.
From reading the above, and from my own current problem, it looks like that's not true: it looks like a child POM will inherit the entire configuration of the plugin, including all executions. In terms of executions, the only thing the child can do is to override specific values - it cannot pick which executions to run, and which not to.
Is this a bug? What's the use of being able to bind each execution to a phase (or not), if all executions will be run? I've only seen it with maven-dependency-plugin:unpack (bound to package phase), but with other plugins I might just have been lucky...
Damn.
In parent pom you should configure executions with <goals> declared but don't declare <phase>. Then in the child POM you should declare:
<plugin>
<artifactId>some-plugin</artifactId>
<executions>
<execution>
<id>execution-id</id>
<phase>partcular-phase</phase>
</execution>
</executions>
</plugin>
The plugin won't be executed until you define a phase in the child pom. Therefore you'll need to explicitly bind executions to phases in every child POM (or in the middle of hierarchy), but
you won't need to copy-paste configuration of these executions.
Note, that many of plugins have Default Phase, e.g. Enforcer Plugin is bound to validate by default. Even if you don't bind plugin to a phase explicitly, it will be bound anyway and thus the plugin will be executed. To overcome this, use non-existing phase in your parent:
<execution>
<id>execution-id</id>
<goals><goal>some-goal</goal></goals>
<phase>none</phase>
</execution>
You must assign an ID to the execution so maven knows which ones overwrite each other and which are independent.

Is it possible to override the configuration of a plugin already defined for a profile in a parent POM?

In a POM parent file of my project, I have such a profile defining some configurations useful for this project (so that I can't get rid of this parent POM) :
<profile>
<id>wls7</id>
...
<build>
<plugins>
<!-- use java 1.4 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<source>1.4</source>
<target>1.4</target>
<meminitial>128m</meminitial>
<maxmem>1024m</maxmem>
<executable>%${jdk14.executable}</executable>
</configuration>
</plugin>
</plugins>
</build>
...
</profile>
But in my project I just would like to override the configuration of the maven-compiler-plugin in order to use jdk5 instead of jdk4 for compiling test-classes.
That's why I did this section in the POM of my project :
<profiles>
<profile>
<id>wls7</id>
<activation>
<property>
<name>jdk</name>
<value>4</value>
</property>
</activation>
<build>
<directory>target-1.4</directory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>my-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<fork>true</fork>
<executable>${jdk15.executable}</executable>
<compilerVersion>1.5</compilerVersion>
<source>1.5</source>
<target>1.5</target>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
...
</profiles>
and it's not working ...
I even tried to override the configuration in regular plugin sections of my POM (I mean, not for a specific profile but for my whole POM).
What could be the problem ?
To clarify some of my requirements :
I don't want to get rid of the parent
POM and the profile (wls7) defined
inside it (since I need many and many
properties, configurations, ...) and
that is not the process in my
company.
A solution based on duplicating
the parent POM and/or the profile
defined inside it is not a good
one. Since if the responsible of
the parent POM change something, I
would have to report it in mine.
It's just an inheritance matter (extend or override a profile, a configuration from an upper-level POM) so I think it should be possible with Maven 2.
Overriding configurations from a parent pom can be done by adding the combine.self="override" attribute to the element in your pom.
Try changing your plugin configuration to:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>my-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration combine.self="override">
<fork>true</fork>
<executable>${jdk15.executable}</executable>
<compilerVersion>1.5</compilerVersion>
<source>1.5</source>
<target>1.5</target>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
For more information on overriding plugins, see: http://maven.apache.org/pom.html
i had the same issue. By default my maven war plugin excluded a html file. But in my acceptance-tests profile i wanted this file included. So when i added in the maven war plugin again it did not override the default.
To resolve this issue i passed in the combine.self attribute and worked fine.
Default build:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<packagingExcludes>swagger-ui/client.html</packagingExcludes>
</configuration>
</plugin>
Acceptance test profile:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration combine.self="override"/>
</plugin>
Did you try to deactivate the wls7 profile (since maven 2.0.10):
Starting with Maven 2.0.10, one or
more profiles can be deactivated using
the command line by prefixing their
identifier with either the character
'!' or '-' as shown below:
mvn groupId:artifactId:goal -P !profile-1,!profile-2
This can be used to deactivate
profiles marked as activeByDefault or
profiles that would otherwise be
activated through their activation
config.
And then add your configuration in a profile with a different name or directly in your pom.xml.

Maven in multimodule web project: how to put sibling modules output to WEB-INF/classes and not into WEB-INF/lib as JARs?

I have a multi-module Maven project.
By default when I build a web module, all sibling modules of type JAR it depends on are copied to WEB-INF/lib folder. I want output of sibling modules to be placed in WEB-INF/classes folder without packaging to JAR.
More general question may be: how to keep sibling modules' configuration files out of JARs so that they can be edited after deployment easily?
You could use an overlay, although that requires that the sibling be of type war rather than jar. There's also using the dependency plugin to unpack the jar, but it will only unpack the version in your local repository, not the one you just packaged.
As for your 'more general' question, there's the excludes tag for the jar plugin.
In case if somebody is interested, I found this solution. I had exactly the same issue.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/MYPACKAGE_TO_EXCLUDE.jar</packagingExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-MYPACKAGE_TO_EXCLUDE</id>
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>MYPACKAGE_TO_EXCLUDE</artifactId>
<version>${project.version}</version>
<type>jar</type>
<outputDirectory>${project.build.directory}/classes
</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>