2011/07/14

Assembling an executable jar into a timestamped package

I needed to build a package for an executable jar containing all its dependencies, in bzip2 format and with a time stamp in the file-name. This is how a did it:

To generate the time stamp I chose gmaven-plugin but you can use the buildnumber-maven-plugin if you need to relate some build number with your control version system (svn maybe?). Futhermore gmaven is a whole new tool box for a developer!

<plugin>
    <groupId>org.codehaus.gmaven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <version>1.3</version>
    <executions>
        <execution>
            <id>set-timestamp</id>
            <phase>initialize</phase>
            <goals>
                <goal>execute</goal>
            </goals>
            <configuration>
                <source>
                    def timestamp = new Date().format('yyyyMMdd-HHmmss')
                    project.properties.setProperty('timestamp', timestamp)
                </source>
            </configuration>
        </execution>
    </executions>
</plugin>


To assembly the package the job is done in two parts: first, the jar must be generated with a manifest declaring the main class to execute and the jar must contain all the dependencies needed to run. Second, the compressed file containing the jar and some shell scripts must be named using a time stamp


<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2.1</version>
    <executions>
        <execution>
            <id>jar-with-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>org.project.bla.bla.bla.ui.cli.Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </execution>

        <execution>
            <id>dist</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
            <configuration>
                <finalName>ProjectXYZ-${project.version}-${timestamp}</finalName>
                <descriptors>
                    <descriptor>src/main/assembly/distributable.xml</descriptor>
                </descriptors>
            </configuration>
        </execution>
    </executions>
</plugin>

Here an assembly descriptor comes to help, we include some shell scripts and specify output format:

<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>dist</id>
    <includeBaseDirectory>true</includeBaseDirectory>
    <formats>
        <format>tar.bz2</format>
    </formats>
    <fileSets>
        <fileSet>
            <includes>
                <include>**/**jar-with-dependencies.jar</include>
            </includes>
            <outputDirectory>bin</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>${project.basedir}/misc/shellScripts</directory>
            <fileMode>0755</fileMode>
            <lineEnding>lf</lineEnding>
            <includes>
                <include>*</include>
            </includes>
            <outputDirectory>bin</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>

Of course, the assembly descriptor must located in the place declared:

















This, you can build packages like this: ProjectXYZ/target/ProjectXYZ-1.0-SNAPSHOT-20110714-221041-dist.tar.bz2

mvn package

The jar would be called like this:

java -jar ProjectXYZ-1.0-SNAPSHOT-jar-with-dependencies.jar

What a ugly name, maybe I need a installer or a shell script as a wrapper:

#!/bin/bash
java -Xms300M -Xmx300M -jar $PROJECTXYZ_HOME/ProjectXYZ-1.0-SNAPSHOT-jar-with-dependencies.jar $*

Ok, I need a installer.

No comments:

Post a Comment