Run an ant task in maven build phase before war is packaged? - maven

When deploying a webapp I need to update some variables in UI resources, unzip some assets and concat some files, currently this is achieved via an ant task. I'm trying to run this task in the maven build process using something like this...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>deploy-ui</id>
<phase>prepare-package</phase>
<inherited>false</inherited>
<configuration>
<target>
<property name="buildDir" value="${project.build.directory}/${project.build.finalName}" />
<ant antfile="build.xml" target="static-assets" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
The above fails because the files have not yet been copied into target directory. If I set the phase to "package" the ant task runs fine and all the files are created/amended, but it's no help as the .war has already been built before the ant target is run.
Basically, I need to run my ant target near the end of the prepare-package phase.
Having looked though the Lifecycle Reference I can't workout how to expose the more granular Goals to the antrun plugin.
Any ideas?

Since I did not get any answer on my comment I guess that you want to stay using maven-antrun-plugin.
From what I've learned and experienced, if two plugins are to be executed on the same phase, then they will be executed in the order they are declared in pom.xml.
For this to work you will have to add the maven-war-plugin in the <plugins/> list after the maven-antrun-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>deploy-ui</id>
<phase>package</phase>
<inherited>false</inherited>
<configuration>
<target>
<property name="buildDir" value="${project.build.directory}/${project.build.finalName}" />
<ant antfile="build.xml" target="static-assets" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<!-- First step is to disable the default-war build step. -->
<id>default-war</id>
<phase>none</phase>
</execution>
<execution>
<!-- Second step is to create an exploded war. Done in prepare-package -->
<id>war-exploded</id>
<phase>prepare-package</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
<execution>
<!-- Last step is to make sure that the war is built in the package phase -->
<id>custom-war</id>
<phase>package</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
</plugin>
Added some more executions so that the default-war is first disabled, then the war is exploded and lastly the war is packaged.

As you observed this is a place where the lifecycle doesn't provide the granularity needed. I answered a similar question for someone earlier. It's not an exact answer to your question but the technique may apply.

Related

How to resolve the path to an artifact in a maven pom without being a project dependency?

I would like to know if it is possible to resolve the path for a maven artifact without having this artifact as a dependency in the project?
What I am trying to do is to execute an external java code generator via exec-maven-plugin or maven-antrun-plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<executable>java</executable>
<arguments>
<argument>-jar ${de.powerstat.fb:generator:1.0-SNAPSHOT}</argument>
<argument>de.powerstat.fb.generator.CodeGenerator</argument>
<argument>${fb.hostname}</argument>
<argument>${fb.port}</argument>
<argument>${fb.username}</argument>
<argument>${fb.password}</argument>
<argument>${project.build.directory}</argument>
</arguments>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
So the point here is how to solve the jars path for ${de.powerstat.fb:generator:1.0-SNAPSHOT} without having it as a dependency of the whole project? Also using the exec:java goal is not a solution, because this one seems to have different problems, but thats another question.
Using the antrun plugin I come to the same problem:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<target>
<java fork="true" failonerror="true" module="de.powerstat.fb.generator" modulepath="${de.powerstat.fb:generator:1.0-SNAPSHOT}">
<arg value="${fb.hostname} ${fb.port} ${fb.username} ${fb.password} ${project.build.directory}"/>
</java>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
So question is again how to solve the modulepath="${de.powerstat.fb:generator:1.0-SNAPSHOT}"?
Solutions that use the maven dependency plugin with the goal dependency:properties will not work in this scenario.
I suggest to use dependency:copy to copy the JAR to some place in /target. Then you can add that path to the antrun or exec plugin.

why list the goals of a plugin without binding to a phase?

Please consider this pom excerpt taken from jacoco example ( http://www.eclemma.org/jacoco/trunk/doc/examples/build/pom-it.xml)
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5-SNAPSHOT</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-report-integration</id>
<goals>
<goal>report-integration</goal>
</goals>
</execution>
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<!-- implmentation is needed only for Maven 2 -->
<rule implementation="org.jacoco.maven.RuleConfiguration">
<element>BUNDLE</element>
<limits>
<!-- implmentation is needed only for Maven 2 -->
<limit implementation="org.jacoco.report.check.Limit">
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.60</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<executions>
<execution>
<id>default-integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Now I know that you can bind a plugin's goal to a maven phase, that is run that goal when maven executes a specific phase.
What is the point of just listing the integration-test goal for the maven failsafe plugin without binding it to something?
The same as for jacoco report and others goal? I don't think you can force the plugin to execute just those listed goals right?
Many thanks
The point is that a plugin can define default life cycle phases where the appropriate goal is bound to (many plugins do this). In this cases you don't need to specify the life cycle phase within the pom file explicitly.
For example the maven-failsafe-plugin has a goal integration-test. This goal has a default binding to the integration-test life cycle phase. Here an excerpt from the documentation:
Description:
Run integration tests using Surefire. Attributes:
Requires a Maven project to be executed.
Requires dependency resolution of artifacts in scope: test.
The goal is thread-safe and supports parallel builds.
Binds by default to the lifecycle phase: integration-test.
That's the reason why you don't need to give a life cylce phase in the configuration like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<id>default-integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
The same is meant for the jacoco maven plugin.
If I understand correctly, M2E will execute the plugin goal during workspace full or incremental builds.
The following article may shed some light:
http://eclipse.org/m2e/documentation/m2e-execution-not-covered.html
You are correct that, on command line, you would not be able to specify the goal, since it is a plugin goal and not tied to a phase. This could be an oddball usage specifically for M2E integration.

Maven-antrun No ant target defined - SKIPPED

i am trying to copy a file in my maven multi-module project via antrun plugin. the file is in root of parent project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<inherited>false</inherited>
<executions>
<execution>
<inherited>false</inherited>
<id>copy</id>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target name="copy and rename file">
<copy file="${basedir}/portal-ext.properties" tofile="${liferay.auto.deploy.dir}/../portal-ext.properties" />
</target>
</configuration>
</execution>
</executions>
i run this via mvn antrun:run the problem is i get "No ant target defined - SKIPPED" on parent and on every module. i need it to run only on parent and thought <inherited>false</inherited> would help but i doesn't. But why "No ant target defined"?
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>ant-execute</id>
<configuration>
<target>
<echo message="plugin classpath: " />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
command : mvn antrun:run#ant-execute
antrun:run will only consider the plugin's configuration, not that for a specific execution, so the execution you specify is ignored. As Run a single Maven plugin execution? states, you can give your execution an id of default-cli to have it picked up.
However, the execution you configure should already be taking effect during the regular build lifecycle.
just run it like this: mvn antrun:run#copy

Maven Tycho: How to Exclude eclipsec.exe in a product build?

I switched the build of our Eclipse RCP product from PDE-build to Maven Tycho. In addition to the main (branded) launcher executable, the product now includes the "eclipsec.exe" file. We would like to omit this console-based launcher from our product as it might confuse our customers. Is there a way to do that with Tycho?
I got this answer on the tycho-users list:
In your eclipse-repository project, assuming that you have a .product file, you can place another file in the same directory called .p2.inf
For the contents of your p2.inf file you can put a p2 touchpoint to remove the file:
instructions.configure=org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/eclipsec.exe);
I don't know how to solve with tycho directly, but you can achieve this with the maven-antrun-plugin. There's a little trick to get the deletion of the eclipsec.exe on the timely position.
You have to put the delete step between materialize and the archive goal of the p2-director-plugin. I put the delete step on the phase pre-integration-test and moved the archive step to the phase integration-test.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>delete-eclipsec.exe</id>
<phase>pre-integration-test</phase>
<configuration>
<target>
<delete file="${project.build.directory}/products/<<your.product.id>>/win32/win32/x86/eclipsec.exe"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-p2-director-plugin</artifactId>
<version>${tycho-version}</version>
<executions>
<execution>
<id>materialize-products</id>
<goals>
<goal>materialize-products</goal>
</goals>
</execution>
<execution>
<id>archive-products</id>
<phase>integration-test</phase>
<goals>
<goal>archive-products</goal>
</goals>
</execution>
</executions>
</plugin>
The result: No eclipsec.exe in the product.zip.
Hope that helps.

How to bind ant to a maven-plugin custom goal

The way to integrate maven with ant is to simply use the maven-antrun-plugin like
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>package</id>
<phase>package</phase>
<configuration>
<tasks>
<ant antfile="build.xml" target="package" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
in your project's pom.xml file
However I want to be able to have that associated build.xml script along with the execution configuration as part of a maven plugin that defines a custom packaging and a lifecycle.
Is there a way to do that?
I wrote an experiment that did this a little while ago. Have a look at the maven-plugin-in-ant branch of jslint4java.

Resources