Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 282
Gili Avatar asked Aug 24 '10 16:08

Gili


People also ask

Are Maven dependencies included in jar?

Apache Maven Shade Plugin provides the capability to package the artifact in an uber-jar, which consists of all dependencies required to run the project.

Does a jar file contain all dependencies?

Normally, when we package a project into a jarW file, the jar file doesn't contain its dependencies, so the dependency jar files would need to be included in the classpathW in order to execute a class in the project's jar file that uses one of the dependencies.

Which Maven command creates an executable jar file with all dependencies of the project?

Use the maven-shade-plugin to package all dependencies into one über-JAR file. It can also be used to build an executable JAR file by specifying the main class.

How do you get dependencies of a jar?

Main class in the tools. jar file. Use the -verbose:class option to find class-level dependencies or use the -v or -verbose option to include dependencies from the same JAR file. Use the -R or -recursive option to analyze the transitive dependencies of the com.


2 Answers

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> 
like image 94
Pascal Thivent Avatar answered Oct 14 '22 18:10

Pascal Thivent


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.

like image 35
PShetty Avatar answered Oct 14 '22 17:10

PShetty