Include jar-with-dependencies in separate assembly? - java

I'm using the maven assembly plugin to package a distributable ZIP archive. However, I would like to include the result of a separate assembly, jar-with-dependencies, inside my final archive. How can I do this? I realize that I could probably just include the JAR manually, but how can I ensure that my custom assembly will run after the JAR assembly?

You can use a multimodule project for that:
parent
|- ...
|- jar-with-dependencies-module
|- final-zip-module
In the jar-with-dependencies module, you assemble the "uber-jar" with all dependencies. The build configuration in the POM should look something like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
In the final-zip-module you can add the jar-with-dependencies as a dependency and use it in the assembly descriptor for the ZIP file. The POM would look something like this:
<project>
...
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>jar-with-dependencies-module</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
And the assembly descriptor would look 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>final-assembly</id>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<!-- Include the jar-with-dependencies -->
<dependencySet>
<includes>
<include>com.example:jar-with-dependencies-module:*:jar-with-dependencies</include>
</includes>
<useProjectArtifact>false</useProjectArtifact>
<!-- Don't use transitive dependencies since they are already included in the jar -->
<useTransitiveDependencies>false</useTransitiveDependencies>
</dependencySet>t>
</dependencySets>
</assembly>
Because of the dependency to jar-with-dependency-module, maven will build the final-zip-module always after your uber-jar was built.

Related

How to make sure that "java" finds the all the required classes when IDE can?

I have a Maven project with only one dependency :
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.8.0</version>
</dependency>
I am using an IDE and it installed all the required dependencies itself. I have written a simple code that uses the classes from net.sf.jasperreports. To create a the package I did mvn package and it created the jar. When I try to run the jar as java -jar myjar.jar, I get an error saying Caused by: java.lang.ClassNotFoundException: net.sf.jasperreports.engine.JRDataSource
I cannot understand how to resolve this. The IDE is able to find the classes but when invoked from command-line, it fails to find the classes. Why is that? What should I do?
I even tried to keep the jasperreports-6.8.0.jar at /Library/Java/Extensions/ but that too did not work.
Here is how the pom.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.suhail</groupId>
<artifactId>JasperCSVDataSource</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<mainClass>com.suhail.main.CommandLineRunner</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.8.0</version>
</dependency>
</dependencies>
</project>
This is the part that uses the maven shade plugin in my project, which is of course totally different from yours:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<artifactSet>
<includes>
<include>org.apache.poi:poi</include>
<include>org.apache.poi:poi-ooxml</include>
<include>org.apache.poi:poi-ooxml-schemas</include>
<include>org.apache.commons:commons-collections4</include>
<include>org.apache.xmlbeans:xmlbeans</include>
<include>org.apache.commons:commons-compress</include>
</includes>
<excludes>
<!-- Exclude main jar to avoid error 'Failed to create shaded artifact,
project main artifact does not exist' -->
<exclude>${project.groupId}:${project.artifactId}</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
Please note that this part of the pom.xml goes into the <plugins> ... </plugins> section, in my case it is below the maven compiler plugin and below the maven jar plugin. You can explicitly include certain dependencies or explicitly exclude certain ones.
The result will be 2 files in your target folder, I personally use the one that has the original name, the other one will have the original name extended by shaded or similar.
If you get an error stating No main manifest attribute in ... then change your configuration of the maven jar plugin as follows:
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
<mainClass>com.suhail.main.CommandLineRunner</mainClass>
</configuration>
Use Maven assembly plugin instead Maven jar plugin.
see what-are-the-differences-between-maven-jar-plugin-and-maven-assembly-plugin!
Maven assembly plugin creates a fully deployable package with all dependencies packed in it.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>com.suhail.main.CommandLineRunner</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

how to create multiple jars with usage specific xml copied to jar - Maven

I am trying to migrate from ANT build to Maven build setup for a very simple codebase setup:
src > Java Classes
conf > META-INF > 3 xml files namely dbConnect-jboss.xml, dbConnect-weblogic.xml, dbConnect-ooc.xml
The goal is to create 3 JARs :
project-jboss.jar, project-weblogic.jar, project-ooc.jar
where each jar will have META-INF/dbConnect.xml, copy of relevant conf/META-INF/dbConnect-xxx.xml.
I tried with [maven-jar-plugin + maven-antrun-plugin ] but the issue is the maven-antrun-plugin does the copy only one time so suppose project-jboss.jar created first then all the rest jars will have same dbConnect.xxx.xml
I need to get a way - how to invoke the copy of dbConnect.xml file via maven-antrun-plugin each time for the respective JAR creation.
screenshot for maven-ant and maven-jar plugin section from pom.xml
Thanks for all those who tried to help me out here, appreciate your helping gesture.
I opted maven-assembly-plugin for the needful.
The following snippet would explain my approach:
<pluginManagement>
<plugins>
<plugin>
<!-- To suppress default JAR creation -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>default-jar</id>
<phase />
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<finalName>${project.artifactId}</finalName>
<useProjectArtifact>false</useProjectArtifact>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
<executions>
<execution>
<id>create-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
Then I created respective assembly xml files for each relevant JAR expected. For example, one of assembly xmls:
<assembly ....>
<id>jboss</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<!-- Avoid getting relevant dependencies included in JAR -->
<includes>
<include>com.vibrant:streamliner.reposerv</include>
</includes>
<useTransitiveDependencies>false</useTransitiveDependencies>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</unpackOptions>
</dependencySet>
</dependencySets>
<files>
<file>
<source>${project.basedir}/config/META-INF/dbConnect-jboss.xml</source>
<outputDirectory>META-INF</outputDirectory>
<destName>dbConnect.xml</destName>
</file>
</files>
Then, I added profile in pom.xml:
<profile>
<id>create-all-jars</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>pom-assembly-jboss.xml</descriptor>
<descriptor>pom-assembly-weblogic.xml</descriptor>
<descriptor>pom-assembly-ooc.xml</descriptor>
</descriptors>
<appendAssemblyId>true</appendAssemblyId>
</configuration>
</plugin>
</plugins>
</build>
</profile>
And, once we execute following - 3 Jars get created:
mvn -P create-all-jars clean package

Exclude file from jar as built by jar-with-dependencies

My pom.xml contains the following to create a jar of my project with all dependencies.
Now I have a properties file in src/main/resources which is necessary to run the application (and I want to use it from starting from the IDE), but I do not want to ship it in the created jar file, as the settings are maintained separately.
Question: How I can I get a file with all dependencies, but exclude those properties files?
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>x.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
As specified by the maven-assembly-plugin documentation:
If your project wants to package your artifact in an uber-jar, the assembly plugin provides only basic support. For more control, use the Maven Shade Plugin.
Using the maven-shade-plugin you can have a fat jar (like using the assembly plugin) and solve similar issues of excluding files via configuration (no need of external assembly descriptor file).
In your case, to exclude resources from assembled jars, you can use shade filters.
A simple configuration would look like:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/*file_pattern*</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
In the example above, you can customize file_pattern or narrow down your filter in the artifact element using your my.groupId:my.artifactId.
Note: the approach above is recommended when excluding files from external libraries, however you can still use the maven-assembly-plugin for excluding files from your own project via a custom assembly descriptor file.
If you want to stick with maven-assembly-plugin you can use an assembly descriptor file where you configure your filters, like in this section:
<fileSets>
<fileSet>
<directory>${basedir}</directory>
<includes>
<include>*.txt</include>
</includes>
<excludes>
<exclude>*.properties/exclude>
</excludes>
</fileSet>
And in your maven configuration, pom.xml you specify the assemblu descriptor file, in the descriptors tag (distribution.xml is a file containing the section from above)
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<filters>
<filter>src/assembly/filter.properties</filter>
</filters>
<descriptors>
<descriptor>src/assembly/distribution.xml</descriptor>
</descriptors>
</configuration>
</plugin>
Also check this link maven-assembly
I faced similar problem (I had a checkstyle-config.xml that, should not be included in the final assembly). A solution below worked for me:
Adding the resources section made my project-jar-with-dependancies.jar not containing checkstyle-config.xml file
Simplified pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<properties>
...
</properties>
<packaging>jar</packaging>
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<excludes>
<exclude>checkstyle-config.xml</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>...</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
...
</dependencies>
</project>

Include entire dependency JAR as JAR within maven project

Is it possible to tell Maven, or one of its common plug-ins, to pack one of my dependency JARs within the final assembly as a JAR file?
ie If I depend on org.some-group:some-artifact:1.2.3, the Maven plug-in would just stuff the entire some-artifact-1.2.3.jar into my final JAR file?
If I understood your question clearly, you need to add one specific jar into your generated jar, in this case you might use use classifier with maven-assembly-plugin
POM.xml
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>jar-with-dependencies-module</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
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>final-assembly</id>
<formats>
<format>jar</format>
</formats>
<dependencySets>
<!-- Include the jar-with-dependencies -->
<dependencySet>
<includes>
<include>org.some-group:some-artifact:1.2.3</include>
</includes>
<useProjectArtifact>false</useProjectArtifact>
<!-- Don't use transitive dependencies since they are already included in the jar -->
<useTransitiveDependencies>false</useTransitiveDependencies>
</dependencySet>t>
</dependencySets>
</assembly>
Above configurations might give you an idea where to start and how you can include specific jars to your final jar

Maven multi-module project compile

I created a C/S framework as a multi-module Maven project. It has three modules: "server", "client" and "common". Classes in "common" module are used both by "server" and "client".
However I don't want a standalone common.jar. Instead, I wish to compile classes in "common" module directly into server.jar and client.jar. Is there any way I can make it?
you can use the maven dependency plugin to unpack the common jar into the other projects.
Use maven assembly plugin with pre-defined descriptor jar-with-dependencies
Option 1:
Include the following in the 'server' project pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
This will include other third party dependency as well, if you have any.
Option 2:
This option is to exclude third party libraries, if any.
1.Create an assembly.xml as follows in the same directory of pom.xml.
<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>custom</id>
<formats>
<format>jar</format>
</formats>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
<includes>
<include>common</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
The include tag must contain <groupId>:<artifactId> format, here just the artifactId 'common' is mentioned as I don't know your groupId.
2.Include the following in the 'server' pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
Run the assembly command (assembly:single).
The best way to accomplish this is to use the maven-shade-plugin.
Add this to your server/client pom:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.7.1</version>
<configuration>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
You will end up with the common classes in the same jar as the server/client.

Categories

Resources