Why won't maven-antrun-plugin run? - maven

I'm having trouble getting the antrun plugin to run.
I have this configuration in my pom:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>compile</phase>
<goals><goal>run</goal></goals>
<configuration>
<target>
<echo message="Hello, maven"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
When I run mvn:compile it runs but all I see in the logs about the antrun plugin is this:
[INFO] --- maven-antrun-plugin:1.4:run (default) # datasite-cms ---
project.artifactId
[INFO] Executing tasks
[INFO] Executed tasks
Why isn't the plugin actually doing anything?

Please use an uptodate version of the maven-antrun-plugin if you really need to use maven-antrun-plugin.
The older versions have using the configuration tag: tasks instead of target. But stop using such ancient versions of Maven plugins.

Related

How do I create an additional jlink artifact on my jar project?

Using the maven-jlink-plugin, I want to create an additional jlink zip file.
I have configured it like so:
<profile>
<id>jlink</id>
<build>
<plugins>
<!-- to be able to package the application using jlink, all dependencies MUST have a module-info.java. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jlink-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>create-runtime-image</id>
<phase>package</phase>
<goals>
<goal>jlink</goal>
</goals>
<configuration>
<launcher>memeforcehunt=memeforcehunt.app/io.github.alttpj.memeforcehunt.app.cli.MemeforceHuntApp
</launcher>
<modulePaths>
<modulePath>${project.build.directory}/modules</modulePath>
</modulePaths>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
But when I try to execute mvn package -Pjlink, I get an error message: There is already an artifact attached to the project.
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 34.657 s
[INFO] Finished at: 2020-12-17T14:33:04+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jlink-plugin:3.0.0:jlink (create-runtime-image) on project memeforce-app: You have to use a classifier to attach supplemental artifacts to the project instead of replacing them. -> [Help 1]
But I cannot add a classifier to the jlink-plugin?
Tag request
maven-jlink-plugin => maven-jlink-plugin
This was a known issue, reported in MJLINK-49 and MJLINK-26, and solved via MJLINK-52 - classifier support. This will be available in version 3.1.0.
Solution for the upcoming 3.1.0 version
Just add a classifier. It will be supported.
Workaround for pre-3.1.0 versions
However, you can create the archive using a workaround.
Change your packaging to <packaging>jlink</packaging> and add a jar execution:
<packaging>jlink</packaging>
<!-- … -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>create-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>appjar</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugins>
</build>
You will get two artifacts out of your project:
groupId:artifactId:version:jlink
and
groupId:artifactId:version:jar:appjar
Please note that the jar will now have a classifier.
Tag request
maven-jlink-plugin => maven-jlink-plugin

Integrate jQAssistant in Maven build using profile and running server

I'm trying to integrate jQAssistant into my existing Maven build. I have a hierarchy of POMs, but basically the top POM defines what the build does. That's where I have my <pluginManagement> and my build plugins that are always used. I also have a couple of Maven profiles for special builds.
So, I want to scan all classes during build time and aggregate the results into a running server to have a fully populated Neo4J database after the build of all my Maven modules. The database should contain my whole code base.
Analysing and checking would be a different step, I don't want to do that directly when building a Maven module.
The examples I see all build a local database and then check the classes against it. As far as I understand it, I would have to run the server as a daemon and then configure the Maven plugin to use the 'bolt' URI to populate it - is this right?
Also, since I don't want to slow down the 'normal' build, I added a Maven profile to active the jQAssistant scan. However, this only works on my top POM, but doesn't work in any other Maven project/module. The inheritance of profiles is a normal and expected Maven feature - so what am I doing wrong?
Here's my parent POM. Just to see whether the profile is active, I added PMD as well:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<groupId>foo</groupId>
<artifactId>parent</artifactId>
<version>1.50.0-SNAPSHOT</version>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<version>1.5.0</version>
<configuration>
<useExecutionRootAsProjectRoot>true</useExecutionRootAsProjectRoot>
</configuration>
</plugin>
</pluginManagement>
</build>
<profile>
<id>architecture</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>pmd</goal>
<goal>cpd</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<executions>
<execution>
<id>scan</id>
<goals>
<goal>scan</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</project>
When I run mvn clean package -P architecture on a Maven project with that parent POM, I see the following output, which shows that the profile is active:
09:30:12.316 [INFO]
09:30:12.316 [INFO] --- maven-pmd-plugin:3.5:pmd (default) # util-type ---
09:30:15.073 [INFO]
09:30:15.073 [INFO] --- maven-pmd-plugin:3.5:cpd (default) # util-type ---
09:30:15.976 [INFO]
However, jqassistant-maven-plugin is nowhere.
Now, if I add it to my normal <build> plugins:
<build>
<plugins>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<executions>
<execution>
<id>scan</id>
<goals>
<goal>scan</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
then I see the following output for mvn clean package for my parent POM:
10:38:14.252 [INFO] --- jqassistant-maven-plugin:1.5.0:scan (scan) # parent ---
10:38:15.684 [INFO] Loaded jQAssistant plugins [CDI, Common, Core Analysis, Core Report, EJB3, GraphML, JAX-RS, JPA 2, JSON, JUnit, Java, Java 8, Java EE 6, Maven 3, OSGi, RDBMS, Spring, TestNG, Tycho, XML, YAML].
10:38:15.952 [INFO] Connecting to store at 'file:/C:/jp/maven-parents/parent/target/jqassistant/store/'
10:38:20.058 [INFO] Initializing embedded Neo4j server 3.x
10:38:20.078 [INFO] Resetting store.
10:38:21.515 [INFO] Reset finished (removed 8453 nodes, 29427 relations).
10:38:22.372 [INFO] Entering C:/jp/maven-parents/parent/target/failsafe-reports
10:38:22.378 [INFO] Leaving C:/jp/maven-parents/parent/target/failsafe-reports (1 entries, 4 ms)
However, in my Maven project, I don't see any jQAssistant output.
Starting mvn help:effective-pom -Parchitecture gives me the same output for the parent project and the Maven module:
<plugin>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.5</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>pmd</goal>
<goal>cpd</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
<configuration>
...
</configuration>
</plugin>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<id>scan</id>
<goals>
<goal>scan</goal>
</goals>
<configuration>
<useExecutionRootAsProjectRoot>true</useExecutionRootAsProjectRoot>
</configuration>
</execution>
</executions>
<configuration>
<useExecutionRootAsProjectRoot>true</useExecutionRootAsProjectRoot>
</configuration>
</plugin>
In my projects I have a parent POM with the following plugin management section:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<version>${jqassistant.version}</version>
<configuration>
<useExecutionRootAsProjectRoot>true</useExecutionRootAsProjectRoot>
</configuration>
<executions>
<execution>
<id>scan</id>
<goals>
<goal>scan</goal>
</goals>
</execution>
<execution>
<id>analyze</id>
<goals>
<goal>analyze</goal>
</goals>
<configuration>
<failOnSeverity>MAJOR</failOnSeverity>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
I also defined the following profile, which I use to run jQAsssistant:
<profile>
<id>verify-architecture</id>
<build>
<plugins>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
Using mvn -P verify-archicture clean install I can scan and analyze my projects.
Here we are, some years later :-)
And coming back to my mistake!
The problem here was the Maven phase. The jQAssistant plugin Mojo scan has the Maven phase post-integration-test by default.
However, we never do mvn clean install in my company, we only do mvn clean package and install using Jenkins, Nexus etc. etc.
So, it was my fault to not force the plugin to the package phase.
That's how it works:
<profile>
<id>jqassistant</id>
<build>
<plugins>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<executions>
<execution>
<id>scan-software</id>
<phase>package</phase>
<goals>
<goal>scan</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

Execute script as part of mvn package

My pom.xml contains
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warName>${project.artifactId}</warName>
<outputDirectory>${wlp.install.dir}/usr/servers/liberty/apps</outputDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
When I run mvn package I can see this step running:
[INFO] --- maven-war-plugin:2.3:war (default-war) # frontEnd ---
That's great. However, I also want to run a shell script before the war file is created. I tried adding
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<configuration>
<tasks>
<exec dir="${basedir}"
executable="${basedir}/src/main/webapp/concat"/>
</tasks>
</configuration>
</plugin>
before the maven-war plugin, but it does not run. I don't even see antrun in the output of mvn. Adding the <tasks> element to the <configuration> for maven-war-plugin does nothing either.
What can I do to have maven simply run a script as part of mvn package?
The position in the pom.xml is irrelevant, you have to bind the maven-antrun-plugin execution to the correct lifecycle phase (e.g. compile) as shown below:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase> <!-- a lifecycle phase --> </phase>
<configuration>
<target>
<!--
Place any Ant task here. You can add anything
you can add between <target> and </target> in a
build.xml.
-->
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
See The maven-antrun-plugin Usage Page for more details and The Maven Introduction to the Build Lifecycle for further reference.

Disable maven plugins when using a specific profile

I'm looking to find a way of disabling a plugin execution if running with a particular profile.
This is the opposite of running a plugin if a profile is selected.
My use case: My Maven build has a whole load of plugins, but when running on my dev machine, I want to skip some of them. Instead of commenting those plugins out locally, I want to be able just run the build with a "dev" profile. The plugins would continue to run on my continuous build.
Ideas?
There is a neat way to disable plugin execution when specific profile is active.
Firstly you need to add an identifier to plugin execution like:
<build>
<plugins>
<!-- (...) -->
<plugin>
<groupId>nl.geodienstencentrum.maven</groupId>
<artifactId>sass-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>styles-compilation</id> <!-- plugin execution identifier -->
<phase>generate-resources</phase>
<goals>
<goal>update-stylesheets</goal>
</goals>
</execution>
</executions>
</plugin>
Then you need to define a profile in which this plugin will NOT be executed:
<profiles>
<profile>
<id>no-sass</id>
<build>
<plugins>
<plugin>
<groupId>nl.geodienstencentrum.maven</groupId>
<artifactId>sass-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>styles-compilation</id> <!-- here there must be the same identifier as defined in <build><plugins> section -->
<phase>none</phase> <!-- this disables plugin -->
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Now if you run standard maven build:
mvn clean package
the sass-maven-plugin will be executed, yet when running:
mvn clean package -P no-sass
the sass-maven-plugin will not be executed.
Define your pom so that is has only the plugins you need in dev mode
Define a dev profile
Define a production profile which contains all plugins you want/need
Define the production profile as default
example pom:
<profiles>
<profile>
<id>production</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<!--
<plugin>
...
</plugin>
-->
</plugins>
</build>
</profile>
<profile>
<id>dev</id>
<!-- Some other logic here, if necessary.
Otherwise, there's no need for another profile. -->
</profile>
</profiles>
To run in Dev Mode you can call the following:
mvn -Pdev compile
To run in Production Mode just use the normal steps:
mvn compile
In case you don't want/need to define anything special in your dev profile, you can omit its declaration and call your Dev Mode like this (! disables a profile):
mvn -P!production compile
Be aware: you may need to escape the exclamation mark since it is a special character in bash:
mvn -P\!production compile
Building on Krzysiek's answer, you don't need to define explicit executions, just have a look at the output maven gives you and disable the default executions.
For instance, given the following output from maven:
[INFO] --- maven-resources-plugin:2.7:copy-resources (prepare-dockerfile) # tilbud ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
...
[INFO]
[INFO] --- maven-resources-plugin:2.7:resources (default-resources) # tilbud ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
....
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:compile (default-compile) # tilbud ---
...
[INFO]
[INFO] --- maven-resources-plugin:2.7:testResources (default-testResources) # tilbud ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
...
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:testCompile (default-testCompile) # tilbud ---
....
The generated default execution names is listed in parenthesis after the plugin and goal. The following profile disables the plugins above:
<profiles>
<profile>
<id>packageOnly</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>default-test</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>default-resources</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testResources</id>
<phase>none</phase>
</execution>
<execution>
<id>prepare-dockerfile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>

Replace task in Maven Antrun Plugin

I am using antrun plugin in my maven build to replace a token #version# in some of the JSP files with the application version.
This is what I am doing:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>compile</phase>
<configuration>
<target>
<echo>${displayVersion}</echo>
<replace file="src/main/webapp/admin/decorators/default.jsp" token="#version#" value="${displayVersion}"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
I am passing displayVersion as a parameter to maven
mvn clean install -DdisplayVersion="Version-1.1"
And this is the console output for Antrun Plugin
[INFO] [antrun:run {execution: default}]
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
main:
[echo] 9.4_70
[INFO] Executed tasks
Although the property is being echoed properly, it's not substituted in my JSP.
The #version# token is replaced by {displayVersion} and not it's actual value.
Use Maven Resources Filtering as Aaron suggested and set the delimiters in the Maven Resource Plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<delimiters>
<!-- enable maven's standard delimiters -->
<delimiter>${*}</delimiter>
<!-- enable your #delimiters# -->
<delimiter>#</delimiter>
</delimiters>
</configuration>
</plugin>
The Maven resources plugin can replace variables in resources; so if you deliver the JSP (instead of compiling it with the jspc plugin), you can simply let the resource plugin do the work while it copies resources by enabling filtering.

Resources