How to remove duplicate content from pom.xml for Maven? - maven-2

I ran into such a situation, when packaging a project using maven, I'd like both the source package and the binary package, and they have the same manifest.mf file. Then I have to write the same entry in both plugin configuration of maven-source-plugin and maven-jar-plugin, like this:
<plugins>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifestEntries>
<Artifiact>${project.name}</Artifiact>
<Version>${project.version}</Version>
<Vendor>${project.organization.name}</Vendor>
<Built-By>Shiva Wu</Built-By>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<manifestEntries>
<Artifiact>${project.name}</Artifiact>
<Version>${project.version}</Version>
<Vendor>${project.organization.name}</Vendor>
<Built-By>Shiva Wu</Built-By>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
It's really not convenient to modify both of them while changing settings. Is there a better way to resolve this?
Thanks:)

There is no better way to handle it than what you are doing.
A couple extra things though. You can stick these configurations into a reuseable "corporate" or "standard" parent POM within the plugin management section and then you won't have to specify them again in any other pom. See here for details:
Best way to share portions of a Maven pom.xml across unrelated projects?
The other thing I notice is that your personal name should be substituted with a variable that should be set from within your settings.xml file. This will help increase build portability.

Related

netbeans maven-assembly-plugin builds jar with dependencies but without project classes

In netbeans 7.2.1 i am trying to build an executable jar with dependencies using the maven assembly plugin. It worked in the past but when building the jar now it contains all dependencies except the classes from the project itself.
When running clean install assembly:single the target directory contains 2 jars, icfStatusPage-1.0-SNAPSHOT-jar-with-dependencies.jar and icfStatusPage-1.0-SNAPSHOT.jar. One contains all dependencies, the other all classes.
The build of the jar with dependencies seems to be ok. (missing pom files are manual installed artifacts).
[assembly:single]
Missing POM for cf:conn-fwk-int:jar:1.0
Missing POM for cf:conn-fwk:jar:1.0
Building jar: /Users/petervannes/NetBeansProjects2/icfStatusPage/target/icfStatusPage-1.0-SNAPSHOT-jar-with-dependencies.jar
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Plugin configuration snippet ;
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.4</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<debug>false</debug>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>nl.organization.icfstatuspage.IcfStatus</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<properties>
Have been googling and trying multiple options with no success till now.
Any help is welcome !
Cheers,
Peter
I was stuck at the same point you were and had trouble finding an answer, so even though this is an older question, since it still came up in the search when I was stuck, this is the answer. I think you need to add in the <executions> section. I know next to nothing about Maven, I'm just trying to make it work... this seemed to do the trick.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>nl.organization.icfstatuspage.IcfStatus</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
<descriptorRefs>
<descriptorRefs>jar-with-dependencies</descriptorRefs>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
I got that section from the Maven documentation on maven-assembly-plugin usage.

buildnumber-maven-plugin and maven-assembly-plugin

I've set up the buildnumber-maven-plugin to pull the version number from SVN and stash it away in the META-INF/MANIFEST.MF inside the jar. That works ok.
But when I try to use it together with the maven-assembly-plugin to pack all the other libs together It doesn't seem to work, the version number stuff is not included in the manifest in the ...-jar-with-dependencies.jar.
Has anybody managed to get them to work together?
Alternatively: Is there a (reasonable simple) way to output the ${buildNumber} into a text file (.properties, perhaps) using Maven? An Ant task in Maven could do it I guess but is there an easier way?
Argh... after posting I found THIS: how to add arbitrary information in manifest from maven assembly plugin and smacked my head.
OK, so My maven-assembly-plugin bit in the pom now looks like this
<build> ... <plugins> ...
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>...</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Implementation-Build>${buildNumber}</Implementation-Build>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

Is there any maven goal that is similar to 'dist'?

I'm working on a project that used ant. I had a target dist that would basically do jar first, and then install the application into a directory.
This means, it would create directories like bin/, lib/ and config/ in the installation directory, and then copy the relevant files into each of these directories.
My question is two-fold:
Is there any maven goal that does this kind of thing?
If not, I want to do maven dist and make this happen. How would you suggest I accomplish this using Maven?
If I can't have my own "target" (like dist), then what would be the best way?
Bottom line: I want to do all this, but don't want to alter the behavior of the default "targets" like compile and package etc.
Thanks,
jrh
PS: I'm using maven version 2.2.21
I don't know what would go in config, but lib and bin is easy.
To copy all dependencies to a folder just do this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/dist/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
To output your jar to a bin folder do this (reference page):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<finalName>${project.artifactId}</finalName>
<outputDirectory>${project.build.directory}/dist/bin</outputDirectory>
</configuration>
</plugin>
Ah, there are additional requirements:
Bottom line: I want to do all this, but don't want to alter the behavior of the default "targets" like compile and package etc.
In this case I'd use a profile to turn this on:
<profile>
<id>dist</profile>
<build>
<plugins>
<!-- insert stuff from above here -->
</plugins>
</build>
</profile>
Now you would do mvn clean package -Pdist to get your dist directory and if you don't add the profile, you get default behaviour.
Basically, things work differently in maven from the way they do in ant. There are no targets, there are only lifecycle phases and plugin goals.
You can either execute a lifecycle phase, which will call all maven plugin goals that are bound to all phases up to this one (e.g. if you do mvn compile, the following phases will be executed: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile). But there is no (easy) way to define a lifecycle phase named dist.
Or you can execute a specific plugin goal (you can actually execute multiple phases and / or plugin goals). E.g. you could write your own dist plugin and call it using mvn dist:dist, but I wouldn't recommend that because you are using existing functionality and the profile solution should be a pretty good fit.
You could try writing an assembly descriptor for the assembly plugin (or search google for a suitable one).
Something like this
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>dist</id>
<formats><format>zip</format></formats>
<fileSets>
<fileSet>
<directory>src/main/config</directory>
<outputDirectory>config</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
</fileSets>
<files>
<file>
<source>${project.build.directory}/${project.artifactId}.jar</source>
</file>
</files>
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
will create a ${project.artifactId}-dist.zip inside your target directory. The zip file will be laid out like
yourProjectName/
yourProjectName/config/...
yourProjectName/lib/...
yourProjectName/${project.artifactId}.jar
It looks like the assembly plugin will only create compressed files, it won't just copy them to a dist folder.
Seans answer is good and I almost went for it until I found out about the appassembler plugin http://mojo.codehaus.org/appassembler/appassembler-maven-plugin/.
See here for an example https://github.com/khmarbaise/maven-training/tree/master/502-assembly-plugin
It is called as part of the package lifecycle.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
<configuration>
<binPrefix>utility</binPrefix>
<assembleDirectory>${project.build.directory}/appassembler</assembleDirectory>
<extraJvmArguments>-Xms512m -Xmx1024m</extraJvmArguments>
<generateRepository>false</generateRepository>
<repositoryName>lib</repositoryName>
<repositoryLayout>flat</repositoryLayout>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<platforms>
<platform>windows</platform>
<platform>unix</platform>
</platforms>
<programs>
<program>
<mainClass>com.soebes.tools.cli.UtilityCLI</mainClass>
<name>utility</name>
</program>
</programs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/bin.xml</descriptor>
<descriptor>src/main/assembly/bin-unix.xml</descriptor>
<descriptor>src/main/assembly/src.xml</descriptor>
</descriptors>
<tarLongFileMode>gnu</tarLongFileMode>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
The descriptors it references are fairly straigtforward and it also creates a batch and shell script for you to run your application!
You cannot have maven dist, with NetBeans (and other IDEs I believe) you can create a custom action dist which executes as mvn install -Pdist (or mvn clean package -Pdist, as suggested by Sean).

How to make jetty-maven-plugin deploy a war that is retrieved from a repository?

I'm setting up an integration test module for a good sized web project. The integration test module is separated from the web project itself, and it has it's own pom.
The idea is to use the maven-soapui-plugin to send requests and verify the response. Setting up the soapui-plugin is no hassle. However, I'm having trouble with figuring out how I can tell the jetty-maven-plugin to deploy a war from a remote repository.
If I have understood correctly, the jetty-maven-plugin has a property called '<webApp>/<webApp>' which lets me specify the war file to deploy. The problem is that the war file is not present in the module itself.
I have heard that I can use the maven assembly plugin to retrieve the war from a repository via the projects artifactId, but I am yet to figure out how I would go about doing so.
Here's a summary of what I want:
Retrieve a specific war from a repository or the like, in example via its artifactId.
Deploy this war to the jetty-maven-plugin (goal deploy-war?)
get maven-soapui-plugin to run tests and report the results back in the integration-test phase.
I am pretty sure I've got step 3 covered, but I am very unsure how to achieve step 1 and 2.
Any help is greatly appreciated
It is maybe possible to use dependency:copy to retrieve the war, unpack it and to get the whole thing working with the maven jetty plugin, but this would be hacky and kinda ugly. A cleaner solution would be to use the Maven Cargo plugin and this is my suggestion. Below, a sample POM showing how to retrieve a WAR artifact using its coordinates and how to deploy it on an embedded Jetty container using Cargo:
<dependencies>
<dependency>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<version>war version</version>
</dependency>
...
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<!-- Container configuration -->
<container>
<containerId>jetty6x</containerId>
<type>embedded</type>
</container>
<!-- Configuration to use with the container or the deployer -->
<configuration>
<deployables>
<deployable>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<properties>
<context>war context</context>
</properties>
</deployable>
</deployables>
</configuration>
<!-- Don't wait, execute the tests after the container is started -->
<wait>false</wait>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
Finally, just bind the soapui plugin on the integration-test phase.
I'm doing the same thing, John, but I took a different approach with the Jetty plugin. I think the end result is the same. I'm developing an integration-test suite to run against several web service WARs. I'm using dependency:copy in the package phase and then a list of <contextHandler/>s configured for maven-jetty-plugin:
<project>
…
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-wars</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/wars-to-be-tested</outputDirectory>
<stripVersion>true</stripVersion>
<artifactItems>
…
<artifactItem>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>version</version>
<type>war</type>
</artifactItem>
…
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.1.3.v20100526</version>
<configuration>
…
<contextHandlers>
…
<contextHandler implementation="org.mortbay.jetty.plugin.JettyWebAppContext">
<war>${project.build.directory}/wars-to-be-tested/artifactId.war</war>
<contextPath>/context</contextPath>
</contextHandler>
</contextHandlers>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>stop</goal>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I would prefer to declare the various wars as dependencies and then use dependency:copy-dependencies to set up the wars-to-be-tested directory; this would allow the Maven reactor to figure out that it needs to build my integration-test module after the wars it'll be testing. The problem I ran into was that the Jetty plugin thought that I wanted to "overlay" all of the wars that were listed as dependencies (a concept that I'd never even heard of until I saw it happen); I don't know if allowing that to happen would have hurt anything, but I didn't like it, so I went with the dependency:copy method.
This is just an alternative to using Cargo. I'll be looking into that myself, but I just wanted to provide another way of doing it.

Can I set the project version with a buildnumber-maven-plugin?

I'm trying to add the svn.revision to project version as a build number and can't seem to do so. My jar has the correct name durin packaging, but its installed in the my local repository it is as if ${buildNumber} is/was undefined when the version was set.
I get foo-1.0.0-SNAPSHOT-${buildNumber} instead of foo-1.0.0-SNAPSHOT-304
Any idea what I'm doing wrong or is adding a revision to the project version a bad idea? Thanks for the help.
<project>
...
<version>1.0.0-${release.identifier}-${buildNumber}</version>
<properties>
<release.identifier>SNAPSHOT</release.identifier>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<executions>
<execution>
<id>useLastCommittedRevision</id>
<goals>
<goal>create</goal>
</goals>
<configuration>
<useLastCommittedRevision>true</useLastCommittedRevision>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</project>
The problem has two parts:
You're trying to set the buildNumber into the version before it is resolved so it will always be ${buildNumber} rather than the resolved value.
Instead of trying to dynamically change the version, you should set the buildNumber into the finalName element in the build. This will create the artifacts with the intended name in the local repository.
The install plugin will ignore the finalName and deploy it as 1.0.0-SNAPSHOT regardless, I don't know of a way to address that. The buildNumber is added to the Manifest if you configure the plugin as below.
So your configuration would be something like:
<version>1.0.0-${release.identifier}</version>
...
<build>
<finalName>${project.artifactId}-${project.version}-${buildNumber}</finalName>
...
</build>
I would avoid using build numbers on SNAPSHOT projects.
Maven provides the SNAPSHOT keyword to signify a volatile project in active development. So if you reference a project with a SNAPSHOT dependency version, Maven will automatically check for updates and keep your dependencies in sync.
If you then add a build number to the end of that version, you will have to manually update the dependencies, so you lose any benefit of having the SNAPSHOT suffix.
I personally avoid using build numbers where possible anyway. If I have to update a project, I just bump the version number, or use a suffix like beta-2 or RC2. If you need to track the revision in the SNAPSHOT, I'd recommend adding it to the Manifest so you can check where the build originated, but use the standard SNAPSHOT suffix to allow Maven to resolve the versions normally. The configuration below shows how to add the revision to the Manifest.
As far as your configuration is concerned, it looks OK to me assuming your SCM url is set up correctly. If you have no SCM configuration in your POM that may be the problem.
Can you run with -X and check for any output from the plugin indicating why it isn't setting the property?
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>0.9.4</version>
<executions>
<execution>
<id>useLastCommittedRevision</id>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.1</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Implementation-Build>${buildNumber}</Implementation-Build>
</manifestEntries>
</archive>
</configuration>
</plugin>
Add this after the buildnumber-maven-plugin:
<plugin>
<groupId>io.github.michaldo</groupId>
<artifactId>nashorn-maven-plugin</artifactId>
<version>0.0.1</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>eval</goal>
</goals>
<configuration>
<script>
$project.artifact.version = "${buildNumber}";
</script>
</configuration>
</execution>
</executions>
</plugin>
And the buildNumber will be recognized by packaging and deploy.