mavenmaven-3executable-jarmaven-assembly-plugin

Extract required libraries using maven assembly plugin


I have a maven project that works fine so far, but building an executable JAR gives me a problem I could not solve so far.

This question here: Why is my .jar file running slower than the program in eclipse?

faces my problem and the method „Extract required libraries into generated jar“ seems to be the solution but i can not find anything how to do this using maven.

Currently I am using the maven assembly plugin but the resulting jar needs ages to start. Starting via IntelliJ needs seconds.

Any advice how to this right? Thx in advance.


Solution

  • The standard executable JAR in Java is only meta information in META-INF/MANIFEST.MF

    1. Main-Class - main class
    2. Class-Path - full list with all dependencies (could be with relative paths)

    With Maven I usually create it in 3 steps:

    1. using maven-dependency-plugin prepare runtime-dependencies
    <plugin>
        <artifact>maven-dependency-plugin</artifact>
        <executions>
            <execution>
                <id>prepare-libs</id>
                <goals>
                    <goal>copy-dependencies</goal>  
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/libs</outputDirectory> <!-- generate folder target/libs with all external JARs -->
                    <includeScope>runtime</includeScope>
                </configuration>
            </execution>
        </executions>
    </plugin>
    
    1. create jar with correct META-INF/MANIFEST.MF using maven-jar-plugin
    <plugin>
        <artifact>maven-jar-plugin</artifact>
        <configuration>     
            <addClasspath>true</addClasspath>
            <classpathPrefix>libs/</classpathPrefix>
            <mainClass>org.super.MySuperMainClass</mainClass> <!-- sure it should be you real mian class -->
        </configuration>
    </plugin>
    
    1. assemble these libs and main JAR in the ZIP file using maven-assembly-plugin
    <plugin>
        <artifact>maven-assembly-plugin</artifact>
        <configuration>     
            <descriptors>
                <descriptor>${project.basedir}/src/assembly/full.xml</descriptor>
            </descriptors>
        </configuration>
        <executions>
            <execution>
                <id>make-full-zip</id>
                <phase>package</phase>
                <goals>
                    <goal>single</goal> 
                </goals>
            </execution>
        </executions>
    </plugin>
    

    full.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
    
        <id>full</id><!-- will be end part of target file name -->
    
        <formats>
            <format>zip</format>
        </formats>
    
        <baseDirectory>/</baseDirectory>
    
        <fileSets>
    
            <fileSet>
                <directory>${project.build.directory}/libs</directory>
                <filtered>false</filtered>
                <outputDirectory>./libs</outputDirectory>
            </fileSet>
    
        </fileSets>
    
        <files>
            <file>
                <source>${project.build.directory}/${project.artifactId}-${project.version}.jar</source>
                <filtered>false</filtered>
                <outputDirectory>./</outputDirectory>
            </file> 
        </files>
    
    </assembly>
    

    As a result of maven build, you will receive a ZIP file (in /target folder) containing your "main" JAR and all dependencies that it requires at runtime. You can expand it in any folder and start it with "java -jar ...".

    P.S. ZIP is a standard Maven artifact, so this ZIP is deployed without any additional movements to the repository (Nexus or Artifactory or etc.). And so, you can simply integrate it into a CD process that creates a Docker container with your application, for example.