Parent pom with definitions that shouldn't be inherited - maven

I am trying to build a parent pom . I'm not using dependencyManagement or pluginManagement. I want all the children to inherit everything.
However, the parent project itself has a specific build requirement that I'm using the maven-jar-plugin for. I don't want the child to inherit this piece. Is there a way to indicate sections that shouldn't be inherited by the child project?
However, the child projects do also use the maven-jar-plugin for another section. Essentially, I have
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
</execution>
</executions>
<configuration>
<archive>
</archive>
</configuration>
</plugin>
I want the configuration section to be inherited by all the children, but the execution section is only for the parent

Put the configuration into <pluginManagement>.
Put the execution into <plugins>.
Use <inherited>false</inherited>.

Related

Avoid inheritance of plugins configurations by external modules

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

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.

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 issue with buildnumber:hgchangeset properties not propagating to children

I have a multi-module project which uses the buildnumber:hgchangeset plugin to generate changeSet and changeSetDate properties, which then get blatted out into the manifest for each module, like so:
pom.xml (parent):
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>hgchangeset</goal>
</goals>
</execution>
</executions>
</plugin>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<ProjectVestion>${project.version}</ProjectVestion>
<ChangeSet>${changeSet}</ChangeSet>
<ChangeSetDate>${changeSetDate}</ChangeSetDate>
</manifestEntries>
</archive>
</configuration>
</plugin>
After a bit of experimentation, I discovered that having buildnumber:hgchangeset execute for each module contributed a significant amount of time to the overall build time, presumably because it's forking hg.exe every time it needs to get the changeset ID of the local repo.
I then thought it would be a good idea to set the inherited property to false on the buildnumber plugin, in order to only have it run once for the parent. Unfortunantly, doing this causes the changeSet and changeSetDate properties to not be "visible" to the child modules.
My question is: is it possible to set things up in such a way that buildnumber:hgchangeset runs only once, but the properties that it sets become visible to children modules?
I suppose alternatively I could write things out to a property file, and have each module read it back in, but this does not seem like idiomatic Maven to me.
Thanks in advance,

How to share POM fragments between different POMs

I am currently struggling with Maven: I have a complex project made of several nested modules and for some of those modules, I have similar configurations in the POMs.
I would like to make it clean. Actually, I would like to define a "runnable-jar" common configuration and activate it in some modules.
Here is the POM fragment I would like to share between several projects:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- Use a custom descriptor, with suffix "bin" -->
<descriptors>
<descriptor>src/main/assembly/runnable-jar-assembly.xml</descriptor>
</descriptors>
<!-- Add main class to manifest -->
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
</configuration>
<!-- Add build of this package to lifecycle -->
<executions>
<execution>
<id>make-runnable-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
In some of the POMS, I would like to be able to do something like:
<!-- Set the main class -->
<properties>
<mainClass>my.main.Class</mainClass>
</properties>
<!-- Activate runnable jar build -->
<import>src/main/pom/runnable-jar-pom.xml</import>
I have searched for a mean to import some XML fragments into a POM, or to define a whole XML nodeset macro.
For what I have found, the closest solution would be to define a profile in the parent POM and activate it in some sub modules by testing the presence of a file. See this related question. But I am facing the problem of the {basedir} property not being set correctly inherited / set.
I find it very surprising to need a hack to do something so basic (=usual). How do you usually handle this in Maven ?
I have just discovered something that might solve my problem :
A module does not require to be a sub-module of its parent module.
Parent and sub-module relationships are separate concepts.
You can specify a parent POM module that is not the actual parent folder in your folder structure, by using the relativePath attribute (as explained in the doc)
In my case, I use the following layout:
main-project
utils (parent:main-project)
cli-programs (parent:main-project)
generic-cli (parent:cli-programs; Dummy & empty POM module)
cli-1 (parent:generic-cli)
cli-2 (parent:generic-cli)
Then, in generic-cli/pom.xml I can declare a configuration that is common to all my cli programs (like custom test suites, runnable-jar packaging, etc).
One way to do this would be to declare your <plugin> code inside <pluginManagement> of the parent pom of your multi-module project. The individual modules can then have a <plugin> section which can use this without redeclaring the contents.
Parent pom:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
... all the details...
</plugin>
...
</plugins>
</pluginManagement>
Child poms:
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
</plugin>
Maven-tiles solves this. It's also on the roadmap for maven 3.x, tracked here.
not a total answer but a solution to the basedir problem is to use a common layout of the modules, e.g. root/modules/moduleA root/modules/moduleB.
You can't build the modules formm their own directory anymore, only through thr parent project. But you can work with the profiles.

Resources