Why does exec-maven-plugin run all phases twice? - maven

When I run a build with maven using the exec-maven-plugin, it runs everything twice for some reason. Is there a way to fix this so it only runs once? I've tried setting my phase in the pom.xml to compile and package and either way, it runs twice. My pom looks like
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<version>1.0</version>
<executions>
<execution>
<id>foo</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>bash</executable>
<commandlineArgs>myscript.sh</commandlineArgs>
</configuration>
</plugin>
</plugins>
</build>

It turned out that adding the phase tag caused the command to get executed twice. Leaving that out, it is now getting run once as expected. I guess it doesn't matter what phase I give it now, it'll always run the goal, which works for me.

If you need to run this early in the build, excluding the phase isn't an option.
You can do something like this instead in the plugin config:
<executions>
<execution>
<id>default</id>
<phase>none</phase> <!-- disable the default execution in validate phase -->
</execution>
<execution>
<id>exec-do-something</id>
<goals>
<goal>java</goal>
</goals>
<phase>generate-sources</phase><!-- now it will run once but in an earlier phase -->
</execution>
</executions>

I saw this happening due to the inclusion of:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
This seems to be that the maven-source-plugin causes a re-execution of the generate-sources phase. See https://maven.apache.org/plugins/maven-source-plugin/jar-mojo.html
Invokes the execution of the lifecycle phase generate-sources prior to executing itself.
If I removed this plugin, the exec goal only executed once.

Related

Spring boot layer jar and build pack

I just started using spring boot 2.3 with layer jar and build pack feature.
Docker image is always built when
mvn clean install/package
code is committed and requested PR in git
However, this will slow down build process, how can I control the phase in which the image is being built and how can I control if image should be built at all?
Following is configuration that added to pom file
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
<image>
<name>${image.name}</name>
<env>
<BP_JVM_VERSION>${BP_JVM_VERSION}</BP_JVM_VERSION>
</env>
</image>
</configuration>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
The build-image goal is attached to the package phase by default. It is run each time the package goal is run because of the executions configuration you have in your pom.xml:
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
If you remove this <executions> block, build-image will not be run automatically, but can be run manually with mvn spring-boot:build-image.
Alternatively, you can attach the goal to a different phase like install by specifying the phase in the <execution> block like this:
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
You can use a spring-boot.build-image.skip property
Add it to the propertied with true value
<properties>
<spring-boot.build-image.skip>true</spring-boot.build-image.skip>
</properties>
so the build-image goal will be skipped by default. Whenever you want to build the image pass false to the cmd
mvn clean install -Dspring-boot.build-image.skip=false
Update:
If you want to change the phase from install to package, you need to configure the plugin as following:
<executions>
<execution>
<id>default</id>
<phase>none</phase>
<goals>
<goal>build-image</goal>
</goals>
</execution>
<execution>
<id>build-image-during-package</id>
<phase>package</phase>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>

Maven tell plugin to not run during phase

Is there any phase I can use to prevent Maven from running a plugin goal or any other way I can tell Maven to skip a plugin goal?
Basically, I want to just run it manually.
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase >pre-integration-test</phase>
<goals>
<goal>wget</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectory>${project.build.directory}/output</outputDirectory>
<url>http://some.url</url>
<outputFileName>filename</outputFileName>
</configuration>
</plugin>
When I use pre-integration-test it runs during mvn install. However, I just want to run it manually.
Phase none worked for my scenario to keep test-jars from being created for specific modules in my multi-module maven project. Like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>test-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>

How to have exec-maven-plugin:exec run before 'site' phase?

I have this script I need to run before site phase to fix an issue (http://jira.codehaus.org/browse/MSITE-640).
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3</version>
<inherited>false</inherited>
<executions>
<execution>
<id>workaround-MSITE-640</id>
<!--it should be 'site' but maven doesn't pick up there-->
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<failWithEmptyArgument>false</failWithEmptyArgument>
<workingDirectory>${project.basedir}</workingDirectory>
<executable>./workaround-MSITE-640.sh</executable>
<arguments>
<argument>${settings.localRepository}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
But I can't seem to run it on that phase. I tried to put it under reporting -> plugins but it can't have configuration there.
It is idempotent, so no problem in running it more than once, but would be nice if I could tie it to the correct phase.
Thanks

Running a plugin goal before the default one

TL;DR: Using maven, I want to run a plugin goal at the beginning of the test phase, before tests actually run. What would be a clean way to do it?
I want to print a message just before the tests actually run. Hence I want to use the echo goal of the echo plugin at the beginning of the test phase (to tell the user that if every tests fail, he'd better have a look at the README since there's a test environment he should set up first)
Attempt n°1
A simple approach could be to run this plugin in the previous phase, process-test-classes.
It works, but it doesn't seem semantically correct to bind this task to this phase...
Attempt n°2
According to Maven documentation, When multiple executions are given that match a particular phase, they are executed in the order specified in the POM, with inherited executions running first., so I tried to set explicitly the surefire plugin:
...
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>maven-echo-plugin</artifactId>
<version>0.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>echo</goal>
</goals>
</execution>
</executions>
<configuration>
<echos>
<echo>*** If most tests fail, make sure you've installed the fake wiki. See README for more info ***</echo>
</echos>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
...
But tests run before my message is printed.
So, to put it in a nutshell: is there a way to reach my goal, or should I stick to the "process-test-classes solution" even though it seems a bit "hacky"?
Thanks!
As #khmarbaise said, your solution is still hacky, because whole test looks like Integration Test and should be processed by Failsafe Plugin. Failsafe has nice phase pre-integration-test for testing fake wiki etc :)
Based on Guide to Configuring Default Mojo Executions this works for me:
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>maven-echo-plugin</artifactId>
<version>0.1</version>
<executions>
<execution>
<id>1-test</id>
<phase>test</phase>
<goals>
<goal>echo</goal>
</goals>
</execution>
</executions>
<configuration>
<echos>
<echo>*** If most tests fail, make sure you've installed the fake wiki. See README for more info ***</echo>
</echos>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<executions>
<execution>
<id>default-test</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
<execution>
<id>2-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
This is very odd for me ;)
I have two plugins with executions bound to generate-sources, one listed first in the list of about 6 plugins and the other listed last. However, the one listed last (which depends on the one listed first) always executes first.
How can I execute several maven plugins within a single phase and set their respective execution order?

Maven - FindBugs Plugin - Exclude from Test Phase

I have the findbugs plugin working fine in my maven setup. I've setup findbugs to execute during the compile phase. I noticed however that it runs during the test phase as well because the test phase also calls compile. Because I have an automated build pipeline that runs all my targets, I don't need findbugs to run during the test phase. I've tried to exclude findbugs from the test phase with the following but no luck yet.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.4.0</version>
<inherited>true</inherited>
<configuration>
<failOnError>${findbugs.failOnError}</failOnError>
<skip>${findbugs.skip}</skip>
<trace>${findbugs.trace}</trace>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
<execution>
<id>findbugs-test-compile</id>
<phase>test</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
It will not be called based on the running through the life-cylcle via compile it simply is running cause you configured to have two executions one in test and one in compile phase. Findbugs should usually run in the reporting area(site).
Just make a single execution:
<executions>
<execution>
<id>findbugs-test-compile</id>
<phase>test</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
The one you like to have. But i recommend to read the documentation cause it should run in reporting area (via site) only.
UPDATE:
If you like to run findbugs only during the site generation than just remove it from the usual build area and put into the reporting area instead.

Resources