Does Maven support multiple variants? - maven

I have a pom for multiple clients, the client specific code is in com.foo.custom. So, for customer A there are classes in com.foo.custom.customerA, for customer B some classes in com.foo.custom.customerB etc. The set of classes in com.foo.custom.customerA is different from those in com.foo.custom.customerB.
When I do mvn package, the code for all the customers shows up in the jar, as expected. Is there a way of selecting just one customer, e.g. mvn package -Dcust=customerB, and then have that one customer in the package and the others not?

You can construct a multi-module project with modules like
common
customerA
customerB
...
The customerX modules use common as dependency.

Here is a pratical solution:
pom.xml fragment
<profiles>
<profile>
<id>ncustomerA</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<includes>
<include>src/main/java/customerA/*</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>ncustomerB</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<includes>
<include>src/main/java/customerA
B/*</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles
Build commands
mvn package -P customerA
mvn package -P customerB
Here https://maven.apache.org/plugins/maven-jar-plugin/examples/include-exclude.html further information.

Related

Maven surefire tests - includes and excludes

I have a class A.java and two test classes, ATest.java and AITests.java. The ITest is for integration. The tests must be performed as:
When no Maven profile is selected only the Atest must be tested.
When the itests profile is activated the both tests (ATest and AITest) must be tested.
The problems is, when I use the command
mvn -P itests test
then only the ATest is tested, without the AITest. But I have no idea what I am missing here. Any hint?
My pom.xml is:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<excludes>
<exclude>**/*ITest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>itests</id>
<activation>
<property>
<name>itests</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
...
For integration tests, please use the Maven failsafe plugin:
https://maven.apache.org/surefire/maven-failsafe-plugin/
You can skip it on the command line if you prefer.

Maven web resource filtering SNAPSHOT version

Using Maven, I'd like to update a parameter in a file to either "true" or "false" based on if the version number is a SNAPSHOT or not. Currently I use the maven-war-plugin to update some other properties based on Maven properties. I've tried to use the maven properties along with the maven-release-plugin, but this seems to not work:
Maven pom.xml:
<project>
...
<properties>
<someProperty>value</somePropery>
<isSnapshot>true</isSnapshot>
</properties>
<profiles>
<profile>
<id>release</id>
<properties>
<isSnapshot>false</isSnapshot>
</properties>
</profile>
</profiles>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<webResources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<releaseProfiles>release</releaseProfiles>
</configuration>
</plugin>
</plugins>
</build>
</project>
Running a mvn release:prepare and mvn release:perform seems to ignore the overridden property in the final war. This seems to stem from the fact that the release profile is active during the release:perform phase, but not the release:prepare phase when the war is actually built.
Is there a better way to do this or am I missing something?
Edit:
I am running this release from a project pom, which this war pom is a submodule.

Why is my target not getting executed?

I am trying to get ready for deployment and therefore I want to copy the correct configuration files to WEB-INF/classes/ before everything gets packed into the WAR file for either deployment or development.
In the end I want to execute deployment-tasks whenever I call
mvn glcoud:deploy
- which is when I need deployment configuration files - and development-tasks whenever something else gets executed in my project directory.
At the moment I have not decided how exactly I'm going to do it but first of all I try to execute such a "dummy task". Unfortunately it is not working.
This is the profile I configured in the pom.xml:
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<configuration>
<target>
<echo message="Hello World!"/>
<copy file="src/main/resource/x.xml" todir="src/main" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
It is supposed to echo "Hello World!" and copy a x.xml file from A to B. I decided to do this in the compile phase which means
mvn clean compile
should actually be enough to get the target executed but .. I wouldn't be here if it worked.
Question: Does somebody know why this is not getting executed?
As mentioned in a comment, I could/should remove pluginManagement from build. However, this would give me an error saying:
Plugin execution not covered by lifecycle configuration: org.apache.maven.plugins:maven-antrun-plugin:1.8:run (execution: compile, phase: compile)
I've added pluginManagement according to an answer of the question "How to solve “Plugin execution not covered by lifecycle configuration” for Spring Data Maven Builds".
The solution below is giving the same “Plugin execution not covered by lifecycle configuration” error
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<!-- -->
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
and I am seeing the same for:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<!-- -->
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profiles>
In order to make m2e happy and yet being able to meet your requirements, try the following:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<configuration>
<target>
<echo message="Hello World!"/>
<copy file="src/main/resource/x.xml" todir="src/main" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
Note the additional plugins section which is basically just repeating the artifactId of the plugin.
What's happening here:
Via the pluginManagement section we are telling Maven: whenever the build (via POM configuration or command line execution) needs to execute this plugin, then apply this version by default and this configuration an executions
The m2e not-so-perfect integration between Maven and Eclipse will then be happy about this plugin configuration, however no plugin execution will ever happen unless we effectively declare it
Via the plugins section we are eventually really defining our build, telling Maven to add this plugin to its build plan. No need to specify version, configuration or executions, since we already defined them into the pluginManagement (that is, management of plugins), which will be applied as default configuration/behavior.
For further details concerning the difference between plugins and pluginManagement, check the reference post on SO: Maven: what is pluginManagement.
Further note on the associated phase for such an execution: the prepare-package phase would be a more (semantically correct and maintenability-friendly) choice than compile. Check the official Build Lifecycle phases list for more details. Concerning prepare-package:
perform any operations necessary to prepare a package before the actual packaging.
Update
It appears that not only as described above the prepare-package phase would be a better choice, but it also the right phase to make the m2e plugin perfectly happy in this case.
See POM Reference, Plugin Management:
pluginManagement
However, this only configures plugins that are actually referenced within the plugins element in the children.
That means declaring a plugin in <pluginManagement> is just half of the story. You have to declare it in a <build>/<plugins> section, too, to actually execute its goal.
In your case:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>

Maven overrides configuration in profiles plugin

I have a 3 maven profiles with plugins:
<profile>
<id>first</id>
<build>
<plugins>
<plugin>
...
<configuration>
<var>1</var>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>second</id>
<build>
<plugins>
<plugin>
...
<configuration>
<var>2</var>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>third</id>
<build>
<plugins>
<plugin>
...
<configuration>
<var>3</var>
</configuration>
</plugin>
</plugins>
</build>
</profile>
When i start my build with mvn clean install -P first,second,third -X, I discovered that all this plugins was executed with configuration from from third profile. Is there any way to preserve my configuration for each of my plugins and not to be overriden by third configuration?
As discussed in comments section, You would have to invoke 3 build activating each profile differently
for example
mvn clean install -Pfirst
mvn clean install -Psecond
mvn clean install -Pthird
and to disable compilation in second and third, you could configure maven-compiler-plugin for these profiles and use skipMain property to disable main's source compilation, also for tests

maven-war-plugin always running even without child pom.xml reference...why?

I am specifying:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<outputDirectory>C:\apache-tomcat-7.0.42\webapps</outputDirectory>
</configuration>
</plugin>
.
.
.
However, even though I do not specify anything in the respective children pom.xml, the war file is still being moved to that output directory.
As far as I know, pluginManagement is only there for reference from the children pom right?
Thank you for your help
By default Maven will invoke the maven-war-plugin war:war goal as part of the package phase if you specify <packaging>war</packaging> in your pom.xml
Since you have a <pluginManagement> stanza for maven-war-plugin specifying a custom <outputDirectory> in your parent pom.xml your child pom.xml will use this property when you run the package phase.
http://maven.apache.org/plugins/maven-war-plugin/usage.html

Resources