Deploying jars for production in Maven - java

I have multiple Java projects (packaged to jars) in my product which have a single pom combining them as modules. Each of the projects has different dependencies and their combined dependencies are defined in the parent pom. I want to prepare the output for production and do the following:
deploy (copy) all my jars to a single location
copy the 3rd party jars from all projects to a different single folder
copy the configuration files (found under the src/main/resources) from all the projects to a third folder.
Anyone knows of a way to do it without having to manually copy each of the above for all the projects? I also want my future projects to support this deployment procedure without having to work too hard and specific.

You need to use Maven assembly plugin for this - here is example of zipping distributive (on production you need then just to unzip):
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
and assembly XML
<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>${env}</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<includes>
<include>com.mycompany:ear-project</include>
<include>com.mycompany:jnlp-project</include>
</includes>
<outputDirectory>libs</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>target/docbook/pdf</directory>
<includes>
<include>index.pdf</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
Please NOTE that for your 2 projects (EAR, JNLP) you can place dependencies via outputDirectory configuration.

I have the same requirements in my project.
There is a difference between using the Jenkins with ClearCase and SVN.
If you were using SVN you should have checked out your projects into your main project, and worked on them like there were on the same dir.
After checking out my child projects I can work on them, in the example you can see a portion from the assembly.xml, in which core and scheduler are the child projects.
</fileSet>
<fileSet>
<directory>./core/src/main/resources/</directory>
<outputDirectory>./examples</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
<fileSet>
<directory>./scheduler/src/main/resources/</directory>
<outputDirectory>./examples</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
This will basically copy the resources folder content into the main project example project.
You can do the same here, if all you projects are on the same vob, and available, you should specify a relative location to which you are going to copy all your resources.
For example:
</fileSet>
<fileSet>
<directory>../../../your_sub_project1/src/main/resources/</directory>
<outputDirectory>./examples</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
<fileSet>
<directory>../../../your_sub_project2/src/main/resources/</directory>
<outputDirectory>./examples</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
This way, when running the primary pom, you will be able to access the content of the sub projects and copy the resources to a certain folder.
Hope it helps..

I will summarize What I did in the assembly XML (to answer all of my issues) in addition to Andrey Borisov answer.
deploy (copy) all my jars to a single location [Used the "moduleset" element]
copy the 3rd party jars from all projects to a different [Used the "dependencySets" element]
copy the configuration files (found under the src/main/resources) from all the projects to a third folder. [Used the "fileset" element]
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
bin
dir
false
<moduleSets>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<binaries>
<outputDirectory>modules</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>my DIR 1</directory>
<excludes>
<exclude>*log4j*</exclude>
</excludes>
<outputDirectory>resources</outputDirectory>
</fileSet>
<fileSet>
<directory>my DIR 2</directory>
<outputDirectory>resources</outputDirectory>
</fileSet>
</fileSets>

Related

Zip/tar the generated jar file along with other file

I need to zip the generated jar file after running the mvn clean deploy.
But i am facing problem with it.
I am using assembly plugin and my assembly.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>bin</id>
<baseDirectory>/</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources/process.sh</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
and pom.xml looks like below.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/assembly/assembly.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- this is used for inheritance merges -->
<phase>package</phase>
<!-- append to the packaging phase. -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
In above case i tried to tar the entire target folder. It got compressed but there was no files.
What am doing is first executing mvn clean then executing mvn clean deploy.
I just want the generated jar/war file to be compressed after execution of mvn clean deploy.
after running mvn clean deploy its zipping the .jar file, its zipping the .jar.original. which is of 8kb file.
Any help will be appreciated.

Add scala test-case to jar file in maven project

I want to include scala test case to the jar file. I have maven project.
I have used following :
<assembly>
<id></id>
<formats>
<format></format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<includes>
<include>...</include>
</includes>
</dependencySet>
<dependencySet>
<outputDirectory></outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.directory}/test/scala</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*.class</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
</fileSets>
Can anybody tell me what is the way to add scala testcase into jar file using
mvn clean package
Thanks.
You need to create a fat jar with test-classes and external dependencies. The Maven Assembly Plugin is the obvious choice:
Plugin example:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>com.example.MainTest</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
You also need to create a descriptor file, in the src\main\assembly folder an assembly.xml file with the following content:
An example:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>fat-tests</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>test</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.directory}/test-classes</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*.class</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
</fileSets>
</assembly>
Build Jar:
mvn clean compile test-compile assembly:single
Run Jar:
java -jar fat-jar-include-tests.jar

how to exclude project class files when using maven assembly plugin?

I am using maven assembly plugin to package all my dependencies in a zip inside lib folder.
I am also adding the project artifact using
<useProjectArtifact>true</useProjectArtifact>
The only problem is that in the final zip I am also seeing the project class files. I want to exclude them since lib already contains the artifact, but after trying various options, no success so far.
here is my assembly.xml
<assembly>
<id>binary</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
The classes of your project appear in your assembly because your are including them in your assembly with this :
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
So if you don't want your project's classes in your assembly then you have to remove this part from your assembly descriptor.
As a reminder, the variable ${project.build.outputDirectory} is by default the folder target/classes.

Maven project depending on two versions of the same artifact

I have a project with two seperate modules that uses sqlline and another library(say OtherLib) that depends on jline. However on different versions.
External Libraries
Module1 uses Sqlline depends on jline 2.10
Module2 uses OtherLib depends on jline 0.9.94
And the two versions are incompatible.
Therefore I have set the classpaths such that Module1 will search in $HOME/lib/module1 folder first and Module2 in $HOME/lib folder first.
Is there a way to specify maven to download the artifact to a source directory first(say ../resources/lib) and then copy it to package during packaging time in assembly.xml?
I know that for copying from source directory the following code can be used.
<fileSets>
<fileSet>
<directory>../resources/lib</directory>
<outputDirectory>${HOME}/lib/module1</outputDirectory>
<directoryMode>755</directoryMode>
<fileMode>644</fileMode>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
Also to get maven to download the dependency I can use (for Module2)
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>${HOME}/lib</outputDirectory>
<directoryMode>755</directoryMode>
<fileMode>644</fileMode>
<includes>
<include>jline:jline:jar:0.9.94</include>
</includes>
</dependencySet>
<dependencySets>
How can I make sure jline:jline:jar:2.10 is downloaded to ../resources/lib folder first?
If you're absolutely sure, what you're doing, you can repackage one of the version using something like maven-shade-plugin. But please be absolutely sure, what you're doing.
With maven-shade-plugin you could create a new Maven module, say jline:jline_2_10:jar:1.0 and use jline:jline:jar:2.10 as a dependency. The maven-shade-plugin would then package it in your jline_2_10-1.0.jar.
Since your new artifact has its own groupId:artifactId combination, there will be no conflicts with the other jline:jline:jar:0.9.94 artifact, so you'll happily have both in the classpath.
I found a an answer here using maven-dependency-plugin
In pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>copy-model</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
<version>2.10</version>
<type>jar</type>
</artifactItem>
<artifactItems>
<outputDirectory>../../resources/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugins>
<build>
And in assembly.xml
<fileSet>
<directory>../../resources/lib</directory>
<outputDirectory>${HOME}/lib/module1</outputDirectory>
<directoryMode>755</directoryMode>
<fileMode>644</fileMode>
<includes>
<include>jline-*</include>
</includes>
</fileSet>
jline-0.9.94 is included in a dependencySet as any other dependency.
I hope this helps. :)

How to create a release package with maven?

I build a desktop application using Maven2.
I'd like to make a release from time to time (just copy all the project's and third party jars into a single dir and generate a run.bat file).
How to do it ?
You need to create run.bat yourself and place it in src/main/assembly/scripts, for example. Then you need to create an assembly.xml file in src/main/assembly.
Here is an example of an assembly.xml file that you might want to use. It creates a tar.gz with all your dependency jars and your run.bat.
<assembly>
<id>1.0</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>target</directory>
<outputDirectory>/lib</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>src/main/assembly/scripts</directory>
<outputDirectory>/scripts</outputDirectory>
<includes>
<include>*.bat</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Finally, in your pom.xml file add the assembly plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>
Now, when you run "mvn install" you should see your tar.gz created.
To release run:
mvn release:prepare
mvn release:perform
OK I got it with a little help of dogbane's answer
I used my own assemlby file src/main/assemlby.assembly.xml
<assembly>
<id>teleinf</id>
<formats>
<format>dir</format>
</formats>
<moduleSets>
<moduleSet>
<includes>
<include>pl..........:core</include>
<include>pl..........:gui</include>
</includes>
<binaries>
<outputDirectory>../../release</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
<fileSets>
<fileSet>
<directory>src/main/assembly/</directory>
<outputDirectory>../../release</outputDirectory>
<includes>
<include>*.bat</include>
</includes>
</fileSet>
</fileSets>
</assembly>
and added following to pom
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
I had to write a run.bat myself - so it's not fully satisfying but will do.
i would go with the maven release plugin, see:
maven release plugin
using maven release plugin
Just an addition to the answer given by dogbane
Your .bat file will running packaged jar file with a filename reflecting the current version of the application, e.g.
java -Xms256m -Xmx350m -jar bin\yourApp-1.10.1-SNAPSHOT.jar
On every release this file will need to get updated with a new version name of the application. This can be automatized, too.
In your pom.xml file add this section:
<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>${project.build.sourceDirectory}/../assembly/scripts</directory>
<includes>
<include>yourApp.bat</include>
</includes>
</resource>
...
</resources>
...
</build>
This asumes that you have put the yourApp.bat file in the folder:
src/main/assembly/scripts
Content of the yourApp.bat file should look like this:
java -Xms256m -Xmx350m -jar bin\${project.build.finalName}.jar
Just run the Maven commands and enjoy.

Categories