Running antrun during war:exploded - maven

For a Maven build I need to copy some files after the exploded directory has been made with the war plugin. Is it possible to run the antrun plugin during/after the war:exploded goal? If so how would I do this? I've tried:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>war</phase>
<goals>
<goal>exploded</goal>
</goals>
<configuration>
<tasks>
<echo>Running ant task...</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
And several other variation but can't seem to get it to run.
Idealy I'd like the ant task to run if I do a full war:war too but I'll cross this bridge when I come to it.

There are at least two ways to achieve it:
Using direct invocation of plugins
When calling mvn war:exploded oder mvn war:war, you only call a specific goal of a specific plugin. No other plugin is executed. Executions defined in pom.xml are not relevant. As a consequence, you could only call several plugin goals directly, for example mvn war:exploded antrun:run.
But be careful when building several modules: mvn war:exploded antrun:run runs antrun after the war plugin for each module. Whereas mvn war:exploded; mvn antrun:run runs the war plugin for all modules and then antrun for all modules.
Using lifecycle bindings of plugins
When calling mvn pre-integration-test, you call all phases of the default lifecycle up to pre-integration-test. You could define an war plugin execution for goal "exploded" in phase "package" and an antrun execution for goal "run" in phase "pre-integration-test".
There is no phase "war" in the default lifecycle. So your example above won't work with the default lifecycle. And for a custom lifecycle with custom phases, you need custom plugins.

Related

When plugin goal is executed: before or after declared phase?

I have a question about maven pom. I have this pom.xml
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Hello world!</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
when the goal run is executed? Before or after package phase?
(for Maven lifecycle see Maven lifecycle)
Plugin goal is execute after beginning of declared phase (package), and before beginning of next phase (pre-integration-test).
In this scenerio maven command
mvn package
should print Hello World
Multiple executions in one phase:
Note: In Maven 2.0.5 and above, multiple goals bound to a phase are
executed in the same order as they are declared in the POM, however
multiple instances of the same plugin are not supported. Multiple
instances of the same plugin are grouped to execute together and
ordered in Maven 2.0.11 and above).
and
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.
Source: Introduction to the Build Lifecycle
In the case you have given it will be executed in the package phase, cause you explicit defined it to be executed during the package phase. If you like to get it executed before the package phase you need to use the prepare-package phase instead package.

tomcat-maven-plugin with multi module and war overlay

I have a maven war project (call it projectA) that depends on another maven war (call it projectB). They get integrated using an overlay with the maven-war-plugin. Both projects have the same parent and the same aggregator (different from the parent). I can package the final war successfully without any issue. This is the command I'm running to do that (I'm at the aggregator level when running mvn):
mvn -am -pl projectA package
The reactor build order is parent ➡ projectB ➡ projectA and all is fine.
I'm now trying to use the tomcat-maven-plugin in this build. So I added the tomcat-maven-plugin in the parent pom pluginManagement section and used it in the projectA pom. I'm launching tomcat with:
mvn -am -pl projectA tomcat:run
The reactor build order remains the same. But the tomcat execution is run on projectB (which is also a war) and not on projectA. Actually, projectA build is not even reached.
I've tried with both the org.codehaus.mojo.tomcat-maven-plugin v1.1 and org.apache.tomcat.maven.tomcat6-maven-plugin v2.1, I've found the same behavior.
How can I make tomcat run the final projectA?
Note: The project dependencies are in fact a bit more complicated and there are other sub-projects involved (jars), that's why I'm calling maven with -am (also make).
Ok, so I found a solution. It is to disable the maven-tomcat-plugin for the pojectB, this answer is based on this other question.
Linking the plugin to a specific phase
First I had to link the maven-tomcat-plugin to a phase of my build cycle, so that it is called even if I don't call the plugin directly from the CLI, obviously I choose the integration-test phase. I can now run mvn integration-test -pl projectA to have tomcat being launched with the just build war.
This is how the plugin is declared in the parent:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>run-war</id>
<!-- We link this plugin to some non default phase so that we can disable it in some modules. -->
<phase>integration-test</phase>
<goals>
<goal>run-war</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
and in projectA I just make use of it as declared in the parent:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
</plugin>
</plugin>
</build>
Deactivating the plugin in projectB
Then, in projectB, I link the same plugin (with the same id) to a null/void/empty phase, which ends up disabling the plugin for this project when built for this integration-test phase:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<executions>
<execution>
<id>run-war</id>
<!-- We don't want this plugin to be called from another module build -->
<phase/>
</execution>
</executions>
</plugin>
</plugins>
</build>
With that setup, I can now do a complete build (both projectB, projectA and other dependencies) and launch tomcat with the resulting war in a single run:
mvn -am -pl projectA clean integration-test

What is meant by plugin goal in Maven speak?

I am a newbie to Maven . I am reading up Maven - The complete reference and came across the term Plugin Goals under the Build settings category of a pom.xml file :
In this section, we customize the behavior of the default Maven build.
We can change the location of source and tests, we can add new
plugins, we can attach plugin goals to the lifecycle, and we can
customize the site generation parameters.
Can you please explain with an example what is meant by attaching plugin goal to the lifecycle?
A plugin goal is a thing that a plugin does. Attaching a plugin goal to the lifecycle is saying to maven: when you are going through the lifecycle and are in this phase, trigger this plugin to do whatever the plugin does. This might sound rather confusing, so let's go through an example:
I want to deploy my application to the server each time I call mvn install. For this, in the build section of the pom , I add the following configuration:
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.1.1.Final</version>
<configuration>
...
</configuration>
<executions>
<execution>
<id>deploy-jar</id>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Take a look at the execution part: this describes how to attach the deploy goal of the jboss-as-maven-plugin to the install phase of the build lifecycle.
For further explanation of the maven lifecycle and it's phases, read this

Maven war plugin

Is it possible to have the maven war plugin output to two different locations? I currently have the following in my pom.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<webappDirectory>${webappDirectory}</webappDirectory>
</configuration>
</plugin>
This was already existing in the POM for the gwt maven archetype, and I'm guessing this explodes everything into the webappDirectory(which the gwt plugin then uses for it development mode).
When I do a
mvn war:war
It generate a war file for me in the target directory. So, I suspect its a different plugin configuration than the one in my POM (default behaviour?). How do I override this?
I basically want to accomplish the following:
I would like to have two different resource folders "src/resources/a" and "src/resources/b" , and have one of the folders used in the exploded version (currently in my pom) and the other version used when I do a "mvn war:war"
Per this question How to execute maven plugin execution directly from command line?, Maven doesn't use pom configuration when you invoke a plugin directly (e.g. mvn war:war). Your POM config is telling Maven to run the exploded goal when the compile phase is invoked (i.e when you run mvn [phase] where phase is compile or later).
I suggest you investigate using a separate profile for exploded deployment (called eg exploded), with a different configuration of the resources plugin to copy a different resources directory. Then use mvn compile -Pexploded for the exploded version.

Running tests with maven packaging type "pom"

I'm having some issues running my unit tests when my pom is set to packaging type "pom". At first, it was saying no goals needed for this project, so I added the maven-surefire-plugin to my pom.xml to bind the test phase to the maven-surefire-plugin test goal.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
Now the surefire plugin is getting executed, but it says there are no tests to run. If I change the packaging type to jar and run mvn test then it picks up my tests files.
When I run mvn test -X it says "testSourceDirectory = C:\dev\dsl\src\test\java", which is the correct location. Is the test location different for the packaging type "pom" than for "jar"? I tried adding
<configuration>
<testSourceDirectory>src/test/java</testSourceDirectory>
</configuration>
to the surefire plugin, but it didn't help at all.
As commented by Dave, if you are using pom packaging, it only executes the following lifecycle goals. Refer to this related maven documentation.
package
install
deploy
If you need it to run any other goal, you would need to explicitly specify it. For instance,
mvn clean compiler:testCompile surefire:test

Resources