Maven - skip plugin if property is empty/null - maven

I want to obtain the following behavior: when I specify a value for the property "my.prop", I want the dependency and clean plugins to be executed. If a value is not specified for that property, I want them to be skipped.
I created "my.prop" like this:
<properties>
<my.prop></my.prop>
</properties>
Then I read that profile activation works only for system properties, so I deleted the above and used the surefire plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<systemPropertyVariables>
<my.prop></my.prop>
</systemPropertyVariables>
</configuration>
</plugin>
I tried using profiles, like this:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<skipDependecyAndCleanPlugins>false</skipDependecyAndCleanPlugins>
</properties>
</profile>
<profile>
<id>skip-dependency-and-clean-plugins</id>
<activation>
<property>
<name>my.prop</name>
<value></value>
<!-- I also tried: <value>null</value> without success.-->
</property>
</activation>
<properties>
<skipDependecyAndCleanPlugins>true</skipDependecyAndCleanPlugins>
</properties>
</profile>
</profiles>
Later, for each plugin I do something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<configuration>
<skip>${skipDependecyAndCleanPlugins}</skip>
</configuration>
....
</plugin>
But the plugins are still executed...
How can I determine Maven to skip the executions of the plugins when "my.prop" is empty/null?

The simplest solution would be to use the activation in the following form:
<profiles>
<profile>
<activation>
<property>
<name>debug</name>
</property>
</activation>
...
</profile>
</profiles>
The above means you can define any value for debug which means -Ddebug is enough.
An empty value can't be defined a pom file cause <value></value> is equivalent to <value/> which means the same as not defined.
Update:
I would suggest to use a profile and NOT a property. So you can simply define on command line mvn -Pxyz install or leave it.

You can use my.prop property in plugin's configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<configuration>
<skip>${my.prop}</skip>
</configuration>
....
</plugin>
Now when you execute:
mvn ... -Dmy.prop=true
then plugin will be skipped

You were very close. You can achieve what you described by using the !my.prop syntax in profile activation.
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<skip>${skipDependecyAndCleanPlugins}</skip>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>skip-dependency-and-clean-plugins</id>
<activation>
<property>
<name>!my.prop</name>
</property>
</activation>
<properties>
<skipDependecyAndCleanPlugins>true</skipDependecyAndCleanPlugins>
</properties>
</profile>
</profiles>
According to Maven documentation, the skip-dependency-and-clean-plugins profile will be activated when the system property my.prop is not defined at all.

Here is a solution that directly addresses the OP's original request: the ability to skip a plugin's execution if a POM property (not a system property) my.prop is not defined. This solution relies on the Apache Maven Help Plugin. It is a kludge, but given Maven's paucity of expression prowess, this is about the best you're gonna get. At least it relies on a well-known, hopefully-maintained plugin, and should work 100% of the time. Oh, and it may make your head explode. Or make you cry. Or both. You've been warned.
First declare the latest version of the Maven Help Plugin in the <build><pluginManagement> section:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.3.0</version>
</plugin>
Then add this "secret sauce" in the <build><plugins> section, which will check to see if my.prop is defined:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>set-is-skip-true-or-prefixed</id>
<phase>validate</phase>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>is-skip</name>
<value>_${my.prop}</value>
<regex>_\$\{my.prop\}</regex>
<replacement>true</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
<execution>
<id>set-is-skip</id>
<phase>initialize</phase>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>is-skip</name>
<value>${is-skip}</value>
<regex>_.*</regex>
<replacement>false</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
</executions>
</plugin>
Now you have a POM property (not a system property) named is-skip, which you can use in any later phase to disable a plugin—provided that plugin has a <skip> or similar option taking a Boolean value. If my.prop is not defined at all, is-skip will be set to true; otherwise is-skip will be set to false.
<plugin>
<groupId>org.example</groupId>
<artifactId>foobar-plugin</artifactId>
<executions>
<execution>
<id>foo</id>
<phase>package</phase>
<goals>
<goal>foo</goal>
</goals>
<configuration>
<skip>${is-skip}</skip>
</configuration>
</execution>
</executions>
</plugin>
There is one caveat: don't define my.prop at all, even to the empty string, or this solution will consider it defined and set is-skip to false. Setting is-skip to true if my.prop is set but empty would require an additional regex evaluation clause above. For my use case I didn't need it, as an empty my.prop isn't valid and I didn't define my.prop at all in the parent POM.
I'll leave it to you to understand how it works (my head exploded already when I was writing it), but I'll be happy to answer any questions.
In step #2 above, be sure and put the two regex evaluations in different phases, such as validate and initialize as used here. The reason is because Maven gets confused if you mix in the same plugins in in the same phase a child POM, and may scramble the execution order. (See MNG-5987.) My kludge of a solution relies on the order of evaluation.

Related

Liquibase Parameters not being read correctly in changelog

I am attempting to get some parameters from liquibase.properties read into my changelog file but not having much success.
I am basing my work on the following stack overflow question: Liquibase changelog parameters in liquibase.properties
The following is my liquibase.properties file:
driver:com.mysql.jdbc.Driver
changeLogFile:src/main/resources/changelog/db.changelog-master.xml
url:jdbc:mysql://localhost:3306/localDB
username:root
password:superSecretPassword
verbose:true
parameter.schemaName:dev_tableName
I have a few different liquibase.properties files for different profiles on maven. The following is in my changelog file and the part I am having difficulty with.
<property name="schema" value='${schemaName}' />
The problem is the property is always coming back as the literal value "${schemaName}" and not "dev_tableName". The reason I need this is because there is a reference to another schema in my changelog that changes from environment to environment.
For example dev_tableName and sys_tableName, and I would rather have several liquibase.properties files for each environment as opposed to a full set of changelogs for each environment. Any help would be appreciated, thanks.
Edit:
If it matters- I am building this via Maven with the following settings:
<build>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>${liquibase-version}</version>
<configuration>
<propertyFile>${liquibase.properties.path}</propertyFile>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java/</outputDirectory>
<processor>com.querydsl.apt.hibernate.HibernateAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<liquibase.properties.path>${project.basedir}/src/main/resources/dev/liquibase.properties</liquibase.properties.path>
<env>dev</env>
<versionNumber>${env}-${project.version}</versionNumber>
</properties>
</profile>
For anyone else having the same problem I ended up solving this issue by using Maven resource plugin instead. Link can be found here: https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html

Maven: How to print the current profile on the console?

I'm trying to print the current profile that is active running a build of a Maven Project.
I'm using the maven-antrun-plugin in order to print messages on the console, in combination with a property that refers to the current profile.
I have tried the following properties:
${project.activeProfiles[0].id}
${project.profiles[0].id}
But in both cases it prints the "string" as it is written, without resolving the variable.
This is my test:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>current active profile: ${project.activeProfiles[0].id}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
But this is the result that I obtain:
main:
[echo] current active profile: ${project.activeProfiles[0].id}
Any suggestion will be appreciated.
Thanks.
The maven-help-plugin offers what you need. It has an active-profiles goal.
You can add it to your pom or even call it from the command line (include it in your maven build call). The How can I tell which profiles are in effect during a build? section of the Maven profile introduction page will show you how. In short:
mvn help:active-profiles
As this does not work for you (see comments) here is another solution:
I think the active profiles (there can be more than one!) are not propagated as available variables - but properties are.
So set a custom property in the profile section and use that, like
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<myProfile>default</myProfile>
</properties>
</profile>
<profile>
<id>debug</id>
<activation>
<property>
<name>debug</name>
</property>
</activation>
<properties>
<myProfile>debug</myProfile>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>current active profile: ${myProfile}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
you can add the maven-help-plugin in your pom to display always the active profile
<build>
<plugins>
<!-- display active profile in compile phase -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>show-profiles</id>
<phase>compile</phase>
<goals>
<goal>active-profiles</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
source: https://www.mkyong.com/maven/maven-profiles-example

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>

Skip exec-maven-plugin from Command Line Argument in Maven

By default in my project POM, exec-maven-plugin, rpm-maven-plugin will be executed,
which is not required in local compilation/build.
I want to skip these plugin execution by passing Command Line Arguments
I tried below command to skip them like normal plugins, but didn't work though!
mvn install -Dmaven.test.skip=true -Dmaven.exec.skip=true
-Dmaven.rpm.skip=true
This page should tell you that the name of the argument to be passed by cmdline (i.e. the user property) is called skip, which is a poorly chosen name. To fix this do the following:
<properties>
<maven.exec.skip>false</maven.exec.skip> <!-- default -->
</properties>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<skip>${maven.exec.skip}</skip>
</configuration>
</plugin>
Try -Dexec.skip from specification:
http://www.mojohaus.org/exec-maven-plugin/java-mojo.html#skip
Using profiles (as little as possible) and execution phase you may achieve what you want for plugins that do not handle the skip property:
Plugin configuration:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rpm-maven-plugin</artifactId>
<executions>
<execution>
<phase>${rpmPackagePhase}</phase>
<id>generate-rpm</id>
<goals>
<goal>rpm</goal>
</goals>
</execution>
</executions>
<configuration>
...
</configuration>
</plugin>
Profile configuration:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<rpmPackagePhase>none</rpmPackagePhase>
</properties>
</profile>
<profile>
<id>rpmPackage</id>
<activation>
<property>
<name>rpm.package</name>
<value>true</value>
</property>
</activation>
<properties>
<rpmPackagePhase>package</rpmPackagePhase>
</properties>
</profile>
</profiles>
Invocation:
mvn package -Drpm.package=true [...]

How to "put" maven command line in pom.xml?

How can I "put" a command line parameter to be executed from pom.xml.
For example I have:
mvn clean install -Dmyparameter
And I wish It to be executed from pom.xml instead from command line.
It depends on which phase you need to use the args. It can be done on plugins by changing the configuration parameter.
<pluginManagement>
<plugin>
......
......
<artifactId>maven-release-plugin</artifactId>
<configuration>
<arguments>-Dmaven.test.skip=true -D[other arguments that u need to include]</arguments>
</configuration>
......
......
</plugin> </pluginManagement>
Same way in the sure fire plugin u can skip test and so on!!
You can try to use maven-exec-plugin:
mvn clean install exec:exec -Dexecutable=<absolute path to binary>
Also it can be bound to some phase of lifecycle to be executed in the middle of the build (without explicit call by exec:exec) and defined in profile with activation if property exists to run optionally:
<profiles>
<profile>
<id>exec</id>
<activation>
<property>
<name>executable</name>
</property>
</activation>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>exec</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<executable>${executable}</executable>
</configuration>
</plugin>
</plugins>
</profile>
</profiles>

Resources