Running maven goal in multiple lifecycles - maven-2

I have a case where I want to run the cobertura plugin in both the verify phase and the reporting phase. I have two profiles and they should both be running the cobertura plugin, but in profile A, I only want to create the xml/html output, but in profile B, I will be generating full site documentation that includes these results.
I have cobertura configured as a plugin that runs as part of the verify phase, but if I do that, even if I run mvn verify site, the cobertura report does not appear in the site documentation. It seems as though I need to have it listed in both the plugins and the reporting section (since I won't be running site in profile A, it won't get called in that profile if I only have it in the plugins). So far the plugins section of my POM includes:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin </artifactId>
<version>2.2</version>
<configuration>
<instrumentation>
<excludes>
<exclude>com/somepkg/**</exclude>
</excludes>
</instrumentation>
<formats>
<format>xml</format>
<format>html</format>
</formats>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
</executions>
</plugin>
I don't want to copy this into the reporting section too since this is a lot to duplicate. Is there a good way to accomplish this otherwise?
Thanks,
Jeff

Define this:
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
<execution>
<phase>pre-site</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
</executions>

Related

Maven: downloading files from url

Can I download some files from http while maven lifecycle? any plugin?
If the file is a Maven dependency, you could use the Maven Dependency Plugin which has a get goal.
For any file, you could use the Antrun plugin to call Ant's Get task.
Another option would be the maven-download-plugin, it has been precisely created to facilitate this kind of things. It's not very actively developed and the documentation only mentions an artifact goal that does exactly the same thing as dependency:get but.. If you look at the sources, you'll see that is has a WGet mojo that will do the job.
Use it like this in any POM:
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.3.0</version>
<executions>
<execution>
<!-- the wget goal actually binds itself to this phase by default -->
<phase>process-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>http://url/to/some/file</url>
<outputFileName>foo.bar</outputFileName>
<!-- default target location, just to demonstrate the parameter -->
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Key benefits of this plugin are caching of the download and checking against a signature, such as MD5.
Note that this answer has been heavily updated to reflect changes in the plugin as noted in the comments.
Seems like wagon-maven-plugin from CodeHaus allows to download files over HTTP (though this is not is original goal).
Here is an example downloading GlassFish zip before integration tests:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>download-glassfish</id>
<phase>pre-integration-test</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>http://download.java.net</url>
<fromFile>glassfish/3.1/release/glassfish-3.1.zip</fromFile>
<toDir>${project.build.directory}/glassfish</toDir>
</configuration>
</execution>
</executions>
</plugin>
The maven-antrun-plugin is a more direct solution:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>download-files</id>
<phase>prepare-package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- download file -->
<get src="http://url/to/some/file"
dest="${project.build.directory}/downloads/"
verbose="false"
usetimestamp="true"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
I'd like to add a few thing about the download-maven-plugin:
Project is now hosted on GitHub https://github.com/maven-download-plugin/maven-download-plugin
Its releases are available on Maven Central, and the SNAPSHOTs are available on the oss.sonatype.org snapshot repository
Compared to other suggestions mentioned here, the download-maven-plugin adds the following interesting feature: caching of files (to avoid always redownloading big files) and signature verification to make sure download got the right bits.
If available, wget can be used directly with exec-maven-plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>wget</executable>
<arguments>
<argument>http://example.com/file.zip</argument>
<argument>destination.zip</argument>
</arguments>
</configuration>
</plugin>
You can use the download-single goal in the wagon plugin. Here is an example to download an HTML page (notice that the URL have to be split in a "directory" url and a "file name")
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals><goal>download-single</goal></goals>
<configuration>
<url>http://www.mojohaus.org/wagon-maven-plugin</url>
<fromFile>download-single-mojo.html</fromFile>
<toFile>[my dir]/mojo-help.html</toFile>
</configuration>
</execution>
</executions>
</plugin>

How to declare a before and after execution of a maven plugin around another plugin execution?

I would like to create an execution order in my plugin which surrounds a maven plugin with a before and after execution of another maven plugin. All 3 executions are part of the deploy phase.
Here is an example of what I want to do:
phase:deploy
url:get: execution-before
dependency:unpack
url:get: execution-after
Note: url:get is my own custo mojo and just executes an http get using commons httpClient.
I would usually attach the after plugin execution in the next phase but unfortunately deploy is the last phase of the jar lifecycle.
Thank you in advance,
Kostas
Note: The following plugins segment from my pom file creates the following execution order which is not expected:
phase:deploy
url:get: execution-before
url:get: execution-after
dependency:unpack
Plugin segment:
<plugin>
<groupId>com.blabla.stpadmin</groupId>
<artifactId>maven-url-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>stop-stpadmin-service</id>
<phase>deploy</phase>
<goals>
<goal>get</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>deploy</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.blabla.stpadmin</groupId>
<artifactId>maven-url-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>start-stpadmin-service</id>
<phase>deploy</phase>
<goals>
<goal>get</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
</plugin>
You can bind the execution of each plugin to the same phase and they will be executed in the order you specify. Note they will be executed after the deploy goal has run, so you might want to bind them to the previous phase (install)
Update: to ensure the execution-before and execution-after goals are executed around the dependency plugin execution, you'll need to ensure they are defined in separate plugins. Otherwise the two configurations will be merged and executed sequentially.
If the two executions need to be defined in the same plugin, you can do this by defining a custom lifecycle and invoking that lifecycle before your Mojo is executed via the execute annotation. In this answer I described how to create a custom lifecycle and force it to be invoked before a plugin is run. If you configure the execute-after goal to invoke the dependency-plugin you'll get the execution order you want (you could even invoke the execute-before goal in that lifecycle as well).
The example below will execute the three plugins in order during the deploy phase:
<plugin>
<groupId>custom.url.plugin</groupId>
<artifactId>maven-url-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>execution-before</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>unpack</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>custom.url.plugin</groupId>
<!--specify final execution in a different plugin to
avoid the configurations being merged-->
<artifactId>maven-url-2-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>execution-after</goal>
</goals>
</execution>
</executions>
</plugin>

Running integration tests with Cobertura Maven plugin

I am having trouble getting the Cobertura plugin to run integration tests in Maven. The closest answer to this question I have found is http://jira.codehaus.org/browse/MCOBERTURA-86. However, the issue remains an open bug. I tried the configuration suggested by Stevo on 03/Apr/09, it didn't work.
My POM
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.3-SNAPSHOT</version>
<reportSets>
<reportSet>
<reports>
<report>cobertura-integration</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
which is by the way exactly the same as the configuration fragment provided by Stevo.
From my opinion, the cobertura maven plugin has two big disadvantages. It has no report only goal, all unit tests will run beside surefire again. It creates the code coverage for unit tests only .
I am using the JaCoCo maven plugin now. JaCoCo reuses the surefire and/or failsafe reports to create a code coverage from unit and/or integration test. Furthermore JaCoCo has a good Jenkins integration. Here is an example where JaCoCo uses surefire unit tests and failsafe integration tests.
<build>
<plugins>
<!-- Unit tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
</plugin>
<!-- Integration tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<!--
The JaCoCo plugin generates a report about the test coverage. In contrast to the cobertura plugin
JaCoCo can be configured to generate code coverage for integration tests. Another advantage of JaCoCo
is that it reports only, cobertura executes all unit tests again (beside the surefire plugin).
-->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.6.4.201312101107</version>
<executions>
<execution>
<id>jacoco-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>jacoco-integration</id>
<goals>
<goal>report-integration</goal>
</goals>
</execution>
<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules />
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Try to configure a execution phase for that plugin like
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<formats>
<format>xml</format>
</formats>
</configuration>
<executions>
<execution>
<id>cobertura-check</id>
<phase>verify</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
</executions>
</plugin>
That way it works like a charm for me.
After some research found a working config listed from http://jira.codehaus.org/browse/MCOBERTURA-86
Make sure to invoke this with
mvn clean deploy -PbuildWithIntegrationTestCoverage
<profile>
<!-- Build with IntegrationTestcoverage => instrument classes with cobertura before integrationtests starts. -->
<id>buildWithIntegrationTestCoverage</id>
<activation>
<property>
<name>buildWithIntegrationTestCoverage</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>instrument-classes</id>
<phase>package</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add cobertura as dependency to the jetty-plugin (required for instrumented classes) -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.2</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
For anyone stumbling on this question through Google - cobertura-maven-plugin started supporting integration tests in version 2.7, which was published in 2015.
Quoting their website:
Up to version 2.6 there were only one report available: cobertura,
which gave you a coverage report for your unit tests. Since there was
only one, you didn't have to configure it in any way.
Starting with version 2.7 a new report was added:
cobertura-integration-test, which gives you a coverage report for your
integration tests. [..]
Both reports are enabled by default. If you want the old behaviour
with only a coverage report for your unit tests, you need to configure
the plugin ...
If you, like I did, run cobertura report using mvn cobertura:cobertura, you'll need to do mvn cobertura:cobertura-integration-test to get integration tests as well. You can check the details from its manual page.
I found that using the maven-antrun-plugin for multi-module projects including integration and UI tests is the best solution. I used this post to get the Ant goals down and went from there. We now have code coverage reports per module and merged one containing coverage from all tests.
I got the integration tests working with Maven 3.0.3 and cobertura-maven-plugin 2.5.1 by configuring the maven-failsafe-plugin to run during the test phase:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>

Maven-assembly-plugin: custom jar filenames

I use the assembly plugin to create several jars with some classes in it. I need custom names for the resulting jars: app_business.jar app_gui.jar core.jar etc.
Currently I have to following configuration:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>app_business</finalName>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<attach>true</attach>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
an the assembly.xml file:
<assembly>
<id>app_business</id>
<formats>
<format>jar</format>
</formats>
<baseDirectory>target</baseDirectory>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>org/xyz/**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
this creates a file app_business.jar which is perfect. But i have no idea how to create my other files. The option appendAssemblyId doesn't help me, as it creates filenames in the format AppName-app_business.jar. I really need the exact filesname app_business.jar.
Any Idea? Thank you very much!
You can move the configuration element below the execution element of the plugin declaration. This means the configuration will only be applied to that execution. You can then add additional executions of the assembly plugin for your other assemblies.
Here is an example of the modified configuration with two executions, each referencing a different assembly:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-business-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>app_business</finalName>
<descriptors>
<descriptor>src/main/assembly/business-assembly.xml</descriptor>
</descriptors>
<attach>true</attach>
</configuration>
</execution>
<execution>
<id>make-gui-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>app_gui</finalName>
<descriptors>
<descriptor>src/main/assembly/gui-assembly.xml</descriptor>
</descriptors>
<attach>true</attach>
</configuration>
</execution>
</executions>
</plugin>
With this configuration, two additional jars (app _business.jar and app _gui.jar) will be created in the target directory, though be aware if you install the project, only the last artifact assembled will be installed (this could of course be a problem).
To avoid this you would need to change the appendAssemblyId properties to true. The closest you can get in this case is to change the finalNames to "app" and the IDs to "gui" and "business", resulting in app-gui.jar and app-business.jar being packaged and all artifacts being installed.
The standard maven plugins are meant for general, repetitive work. They gather all information from the POM and they are smart (in the sense that you don't need to configure much).
If you need special tasks, then I suggest to use the ant plugin which allows you to embed a piece of Ant code in the POM. This allows you to run the jar task.

Can maven sign not only produced jar, but also dependencies

I managed to create main jar, copy dependencies to a single directory, the only step left is to sign all jars.
I can sign my own produced jar as a part of jar:sign, but how do i sign dependencies?
Thanks
Here are a couple of options:
Use the Maven ant task to run jarsigner from the JDK against all the dependencies.
Use the webstart plugin which can sign all your JARs, even if you aren't using it for the purpose of JNLP-izing your app. I'm using it to actually JNLPize one app.
Look at what the webstart plugin source is doing to iterate over all dependencies and sign them and start a new Maven Plugin/Mojo that does the same thing, sans JNLP.
Onejar your app and its dependencies and just sign that.
add to plug-in config <archiveDirectory>target</archiveDirectory>
If you are using maven-jar-plugin, you can specify which single jar to sign using the "jarPath" setting. The following configuration causes the jar-with-dependencies file to be signed instead of the dependency-less jar file:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>sign</goal>
</goals>
</execution>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- NOTE: The secret key is in shared version control. The
password is in shared version control. This IS NOT
SECURE. It's intended to help avoid accidentally
loading the wrong class, nothing more. -->
<jarPath>${project.build.directory}/${project.build.FinalName}-${project.packaging}-with-dependencies.${project.packaging}</jarPath>
<keystore>${basedir}/keystore</keystore>
<alias>SharedSecret</alias>
<storepass>FOO</storepass>
</configuration>
</plugin>
If you want to sign both, I don't know how to do that with maven-jar-plugin, so you may need to look into the other options mentioned above.
One can also create a single JAR using the maven-assembly-plugin.
Together with the other suggestion by Eric Anderson (of signing another JAR) one can then sign this assembled JAR (instead of the original JAR). Note that the order of the plugin definitions matters here.
It is assumed that sign.keystore.file etc are set elsewhere (e.g. in a profile).
<build>
<plugins>
<!-- It seems that maven-assembly-plugin must be declared before the maven-jar-plugin,
so that it is executed first in the package phase,
and then the signing of the packaged jar can succeed. -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestEntries>
<!-- ... -->
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<jarPath>${project.build.directory}/${project.build.FinalName}-${project.packaging}-with-dependencies.${project.packaging}</jarPath>
<keystore>${sign.keystore.file}</keystore>
<type>${sign.keystore.type}</type>
<storepass>${sign.keystore.storepass}</storepass>
<alias>${sign.keystore.alias}</alias>
<verify>true</verify>
<verbose>false</verbose>
<removeExistingSignatures>true</removeExistingSignatures>
</configuration>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<!-- <addClasspath>true</addClasspath> -->
</manifest>
<manifestEntries>
<!-- ... -->
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>