Maven – Modules and moduleSet VS dependency and dependencySets - maven-2

We have installation folder that we use with maven to pack a release up,
This Installation folder has some static files, and a pom.xml
The build goal is to copy the static files to the target installation folder and some zip artifacts from the repository – expand them and put them in the target folder under /unzipped.
installation folder:
/installation_folder
pom.xml
/some_files
/file1
/file2
Target folder should be like:
/target
/installation_files
/some_files
/file1
/file2
/unzipped
/prj1 - unzipped artifact prj1 from the repository
/prj2 - unzipped artifact prj2 from the repository
On this “installation pom” - I have a reference to assembly xml; I am able to copy the static files - and get artifacs from the repository,
The question is – to copy the zip from repository and expand them in the target/unzipped folder
should I use Modules and moduleSet or dependency and dependencySets?
Should the pom.xml + assembly.xml look like:
project.group
installation_project
pom
<modules>
<module>prj1</module>
<module>prj2</module>
</modules>
...
and assembly.xml:
<moduleSets>
<moduleSet>
<includes>
<include>*:*</include>
</includes>
<binaries>
<unpack>true</unpack>
</binaries>
</binaries>
</moduleSet>
Or should it look like this:
<project>
<groupId>project.group</groupId>
<artifactId>installation_project</artifactId>
<packaging>pom</packaging>
<dependencies>
<dependency>
<artifactId>prj1</artifactId>
<groupId>gruop_id</groupId>
<version>1.0-SNAPSHOT</version>
<type>zip</type>
</dependency>
<dependency>
<artifactId>prj2</artifactId>
<groupId>gruop_id</groupId>
<version>2.0</version>
<type>zip</type>
</dependency>
</dependencies>
...
and assembly.xml:
<dependencySets>
<dependencySet>
<outputDirectory>installation_files/unzipped/</outputDirectory>
<outputFileNameMapping>${artifact.artifactId}</outputFileNameMapping>
<includes>
<include>*:*:zip</include>
</includes>
<unpack>true</unpack>
</dependencySet>
</dependencySets>
Thank you!

Another way would be to just maven dependency plugin, with goal=unpack.
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<type></type>
<overWrite></overWrite>
<outputDirectory></outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
Another way is to use an assembly plugin but i find that quite cumbersome and is usually meant for more complex assembly creation than simple unzipping/zipping.

Related

Create a simple app with user-accessible config files using Maven

I need to produce a simple app for my customer configure and run at their site. I am using the Spring framework, so I have a number of config files that must be on the class path. I am using Maven2 with Netbeans as my IDE.
I am able to create and run my app using Netbeans/Maven and I am using the Application Assembler Maven plugin to generate the runnable application. All this works fine except that my Spring config files have to be placed in src/main/resources which means that they get packaged into the resulting JAR file.
I need my customer to be able to modify the config files to do their testing, but it's not reasonable to ask them to modify the copies that are packaged in the JAR.
There are perhaps a number of solutions, but it seems to me that the simplest would be to get Maven to not package the app and the config files into a JAR at all, just leaving them in something like a classes directory from which they can be run. This would allow the user to modify the config files easily. Unfortunately I can't figure out how to get Maven to "package" the app in this manner, or how to get the AppAssembler to generate the resulting runnable.
Here is an extract of my pom.xml that may help illustrate what I am trying to do:
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.1.0.RELEASE</version>
</dependency>
... stuff deleted ...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<!-- Set the target configuration directory to be used in the bin scripts -->
<configurationDirectory>conf</configurationDirectory>
<!-- Copy the contents from "/src/main/config" to the target
configuration directory in the assembled application -->
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<!-- Include the target configuration directory in the beginning of
the classpath declaration in the bin scripts -->
<includeConfigurationDirectoryInClasspath>
true
</includeConfigurationDirectoryInClasspath>
<platforms>
<platform>windows</platform>
</platforms>
<programs>
<program>
<mainClass>org.my.path.App</mainClass>
<name>app</name>
</program>
</programs>
</configuration>
</plugin>
</plugins>
</build>
...
Neither single packed jar file or bunch of unpacked classes files are good format for professional client delivery. Look at those brilliant apache apps like tomcat, ant and maven, they are shipped as a tar.gz or zip file, after download, simply extract them and you will get a nice and clean directory structure:
conf --> put config file like *.properties, logback.xml here
doc --> readme.txt, userguide.doc etc
lib --> put you core.jar with dependency jar file here
run.bat --> run script for Windows
run.sh --> run script for Unix
We can do these kinds of stuff with Maven as well. Note that you should design and implement your core jar to read *.properties from the conf directory properly. then use maven-assembly-plugin pack you app into this classical directory structure.
Sample pom.xml for a command-line app:
<!-- Pack executable jar, dependencies and other resource into tar.gz -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>attached</goal></goals>
</execution>
</executions>
<configuration>
<descriptors>
<descriptor>src/main/assembly/binary-deployment.xml</descriptor>
</descriptors>
</configuration>
</plugin>
Sample binary-deployment.xml for a command-line app:
<!--
release package directory structure:
*.tar.gz
conf
*.xml
*.properties
lib
application jar
third party jar dependencies
run.sh
run.bat
-->
<assembly>
<id>bin</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/java</directory>
<outputDirectory>conf</outputDirectory>
<includes>
<include>*.xml</include>
<include>*.properties</include>
</includes>
</fileSet>
<fileSet>
<directory>src/main/bin</directory>
<outputDirectory></outputDirectory>
<filtered>true</filtered>
<fileMode>755</fileMode>
</fileSet>
<fileSet>
<directory>src/main/doc</directory>
<outputDirectory>doc</outputDirectory>
<filtered>true</filtered>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
If not misleading, I think you want to let the jar and config to be separated, with jar exposed for client's testing.
The following can do this for you using copy-maven-plugin, it can accomplish almost tasks what assembly-plugin would do ,ex: copy, dependency and much more - download, upload ,move ,... .
<plugin>
<groupId>com.github.goldin</groupId>
<artifactId>copy-maven-plugin</artifactId>
<version>0.2.5</version>
<executions>
<execution>
<id>create-archive</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<resources>
<!--copy your scripts to ${myOutPutPath}/bin-->
<resource>
<targetPath>${myOutPutPath}/bin</targetPath>
<directory>${project.basedir}/src/main/scripts</directory>
<includes>
<include>*</include>
</includes>
</resource>
<resource>
<!--copy your configs-->
<targetPath>${myOutPutPath}/conf</targetPath>
<directory>${project.basedir}/src/main/config</directory>
<include>*</include>
</resource>
</resources>
</configuration>
</plugin>
Package main jar and put to your ${myOutPutPath}
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<!-- The configuration of the plugin -->
<configuration>
<outputDirectory>${myOutPutPath}</outputDirectory>
<!-- Configuration of the archiver -->
<archive>
<!-- Manifest specific configuration -->
<manifest>
<!-- Classpath is added to the manifest of the created jar file. -->
<addClasspath>true</addClasspath>
<!--
Configures the classpath prefix. This configuration option is
used to specify that all needed libraries are found under lib/
directory.
-->
<classpathPrefix>lib/</classpathPrefix>
<!-- Specifies the main class of the application -->
<mainClass>com.xinguard.snmp.SNMP_ETL</mainClass>
</manifest>
<!-- you need to add some classpath by yourself, like conf here for client to use-->
<manifestEntries>
<Class-Path>conf/</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
then package the lib jar to lib directory under jar directory.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${myOutPutPath}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>

Referring exploded war dependency in maven antrun plugin

I have a dependency declared as follows
<dependency>
<groupId>com.abc.webapp</groupId>
<artifactId>mywebapp</artifactId>
<version>1.3.2</version>
<type>war</type>
</dependency>
This war file which is part of an ear is exploded in the target directly and I need to copy a file(version.properties) to the WEB-INF/classes folder of this exploded war directory (target/mywebapp-1.3.2.war/). How can I refer to this folder in the antrun plugin without any hardcoding? Thanks in advance.
I'm going to cheat a bit and ask that you declare the dependency like this, with references to properties:
<dependency>
<groupId>${war.groupId}</groupId>
<artifactId>${war.artifactId}</artifactId>
<version>${war.version}</version>
<type>war</type>
</dependency>
and the properties would look something like this in your pom.
<properties>
<war.groupId>com.abc.webapp</war.groupId>
<war.artifactId>mywebapp</war.artifactId>
<war.version>1.3.2</war.version>
</properties>
Now, you still need to change the war GAV if required, but you only need to do it once, and the <dependency> and copy will both refer to the same thing.
Then maybe you could also use the maven-resouces-plugin and its copy-resource goal.
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/${war.artifactId}-${war.version}.war/WEB-INF/classes</outputDirectory>
<resources>
<resource>
<directory>where_version.properties_is</directory>
<includes>
<include>version.properties</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

Maven WAR Overlays - including unpacked dependencies

I'm trying to set up a project using Maven and am a bit stuck with how to include some third party dependencies that need to be included unpacked in the resultant war file.
My project contains some custom ColdFusion code and includes Java dependencies, including ColdFusion packaged as a war file. I then am attempting to include some 3rd party ColdFusion code, which I've installed in my maven repository packaged as a jar, but I actually want to deploy it unpacked in the resultant war file. It's this unpacking of the 3rd party libraries that I'm stuck with. I'd really like this to be done BEFORE the war is build, so that I can use war:exploded during the development.
Currently my pom.xml looks something like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- This is the war overlay -->
<dependency>
<groupId>com.adobe.coldfusion</groupId>
<artifactId>coldfusion</artifactId>
<version>9.0.1</version>
<type>war</type>
<scope>runtime</scope>
<optional>false</optional>
</dependency>
<!-- This is the 3rd party ColdFusion dependency -->
<dependency>
<groupId>org.corfield</groupId>
<artifactId>fw1</artifactId>
<version>1.2RC2A</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
</build>
</project>
I've kind of got it doing what I want by modifying the build section as follows:
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.corfield</groupId>
<artifactId>fw1</artifactId>
<version>1.2RC2A</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/${project.artifactId}</outputDirectory>
<includes>**/*.cfc</includes>
</artifactItem>
</artifactItems>
<includes>**/*.cfc</includes>
<outputDirectory>${project.build.directory}/${project.artifactId}</outputDirectory>
<overWriteReleases>false</overWriteReleases>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The problem with this is that the package:unpack happens after the war is built, so the unpacked dependecies are not in the resulting war file.
I have also tried a few things with the assembly plugin and I came fairly close also by using something like this:
<assembly>
<id>${project.artifactId}</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<includes>
<include>org.corfield:fw1</include>
</includes>
<unpack>true</unpack>
<outputDirectory>/</outputDirectory>
</dependencySet>
<dependencySet>
<excludes>
<exclude>org.corfield:fw1</exclude>
</excludes>
<unpack>false</unpack>
<outputDirectory>/WEB-INF/lib</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/main/webapp</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
However that created a second war file named something like my-webapp-1.0-SNAPSHOT-my-webapp.war as well as the my-webapp-1.0-SNAPSHOT.war. The my-webapp-1.0-SNAPSHOT-my-webapp.war also included my-webapp-1.0-SNAPSHOT.war
At the end of the day I want my resultant war to look like:
org
|-- corfield
|-- framework.cfc
WEB-INF
|-- lib
|-- web.xml
index.cfm
(in reality there's a lot more to it than that, but that's enough to illustrate the point hopefully)
I think I'm pretty close but I'm just missing something I need. I'd be extremely grateful for any assistance.
For the maven-dependency-plugin approach, bind the unpack goal on the prepare-package phase (Maven 2.1+) instead of package.
References
Lifecycle Reference
Have you looked at the overlay option with maven-war-plugin? It esstentially allows you to unpack the ColdFusion war on top your site layout. I've done this with a combination of ColdFusion 9.x and Struts2. Doing a ColdFusion only overlay should make it real easy. You may want to create the ColdFusion war first. You can also then control the neo-*.xml files from your Maven project as well.

Maven: Packaging dependencies alongside project JAR?

I'd like Maven to package a project alongside its run-time dependencies. I expect it to create a JAR file with the following manifest:
.....
Main-Class : com.acme.MainClass
Class-Path : lib/dependency1.jar lib/dependency2.jar
.....
and create the following directory structure:
target
|-- ....
|-- my-project.jar
|-- lib
|-- dependency1.jar
|-- dependency2.jar
Meaning, I want the main JAR to exclude any dependencies and I want all transitive dependencies to get copied into a "lib" sub-directory. Any ideas?
I've like Maven to package a project with run-time dependencies.
This part is unclear (it's not exactly what you describe just after). My answer covers what you described.
I expect it to create a JAR file with the following manifest (...)
Configure the Maven Jar Plugin to do so (or more precisely, the Maven Archiver):
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.acme.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
...
<dependencies>
<dependency>
<groupId>dependency1</groupId>
<artifactId>dependency1</artifactId>
<version>X.Y</version>
</dependency>
<dependency>
<groupId>dependency2</groupId>
<artifactId>dependency2</artifactId>
<version>W.Z</version>
</dependency>
</dependencies>
...
</project>
And this will produce a MANIFEST.MF with the following entries:
...
Main-Class: fully.qualified.MainClass
Class-Path: lib/dependency1-X.Y.jar lib/dependency2-W.Z.jar
...
and create the following directory structure (...)
This is doable using the Maven Dependency Plugin and the dependency:copy-dependencies goal. From the documentation:
dependency:copy-dependencies takes the list of project direct dependencies and optionally transitive dependencies and copies them to a specified location, stripping the version if desired. This goal can also be run from the command line.
You could bind it on the package phase:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
Add the following plugins in pom.xml. Check the value at mainClass,classpathPrefix,addClasspath tags.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>org.apache.camel.spring.Main</mainClass>
<classpathPrefix>lib/</classpathPrefix>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/assembly/some-assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Create some-assembly.xml under src/assembly as below.
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>distribution</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<scope>runtime</scope>
<outputDirectory>/lib</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
Note that useProjectArtifact flag to false, unpack flag to false. If root folder inside zip file is not required,then one can make includeBaseDirectory to false.
This will create name-version-distribution.zip file. Inside zip file, there will be folder name-version. Inside this folder, your executable jar and lib folder containing all dependency jars will be present. Check manifest.MF file of executable jar. It contains both main class and classpath information.
You can use the maven jar plugin, take a look on this page:
http://maven.apache.org/plugins/maven-jar-plugin/examples/manifest-customization.html

Maven Assembly plugin - Include repo jars

I have a multi module project and I am using assembly plugin to build a tar file. I have included all of my modules in assembly plugin using moduleSets tag.
<moduleSets>
<moduleSet>
<includes>
<include>module1</include>
<include>module2</include>
All of my module jars are assembled into a lib folder. I want to add mysql jar from my local maven repository to the same lib folder that contains all of my other modules. Adding local repository jars in moduleset doesnt seem to work.
[WARNING] The following patterns were never triggered in this artifact inclusion filter:
o 'mysql.mysql-connector-java:mysql-connector-java-version'
How can I include jars from maven repository.
I think that you need to declare your mysql jar in the includes subelement of a dependencySet.
Something like this:
<assembly>
<id>my-assembly</id>
...
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<includes>
<include>mysql:mysql-connector-java</include>
</includes>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
...
</assembly>
Refer to the Descriptor Format documentation and/or the chapter 12.5.4. dependencySets Section of the Maven Book for more details on this element.
I don't think you need to do anything special, just make sure mysql is listed as dependency in your project and it should work. Same applied to dependencies on modules - just list them as dependencies. Below is typical configuration of assembly plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
I had the same problem, and solved it by changing scope on pom dependency to compile.
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>compile</scope>
</dependency>