Monday, 2 February 2015

Maven Tip: All about executable jars

An executable jar is an extremely useful artefact when it comes to distributing your code.  It means that, as long as Java is installed on the client machine, on Windows and Mac at least, your users can just double click the jar and program will launch. Alternatively on the command line the program can easily be launched with the simple command line java -jar xxx.jar. No fussing with classpaths and dependent jars.

Creating a executable jar from Maven is pretty straight forward and involves using the maven-assembly-plugin. This can be configured and added to your pom.xml as below:

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.example.Main</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                        <execution>
                            <phase>install</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                </executions>
            </plugin>

Let's drill into the details:
<goal>single<goal> tells the plugin that we want to execute the single goal. For more documentation see here.
<phase>install<phase> tells the plugin that we want this task to be run as part of the install lifecycle event.
<descriptorRef>jar-with-dependencies</descriptorRef> tells the plugin that we want the jar to include all dependencies.
<mainClass>com.example.Main</mainClass> tells the plugin which class should be launched when the jar is executed.

In this case I set up the plugin to produce an executable jar during the install life-cycle but of course you can change that setting if you want it to be part of a different part of the life-cycle.

Another task you will want Maven to do for you is to create your executable jar as part of the release.

In order to do this you will need to configure the maven-release-plugin to create the executable jar. This can be done as below:


<plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-release-plugin</artifactId>
      <version>2.5.1</version>
      <configuration>
           <goals>install</goals>
           <preparationGoals>install</preparationGoals>
      </configuration>
</plugin>

The key thing here is the configuration of the preparationGoals which is called by release:prepare. When configured as a preparationGoal install is executed before committing (default preparationGoals are clean verify). By adding install to the preparationGoals we ensure that our executable jar will be built before the commit.  It will be tagged with the same number as the release.  If we are moving from version 1.3 to 1.4 the executable jar will be named xxx-jar-with-dependencies-1.4.jar.

Compare what happens when you configure install as a completionGoal as opposed to a preparationGoal. In the same example as above, moving from version 1.3 to 1.4, if install was configured as a completionGoal, install would be run after the commit and the resulting executable jar would be called xxx-jar-with-dependencies-1.5-SNAPSHOT.jar.

Goal (as opposed to preparationGoal and completionGoal) is run by release:perform. By default it calls deploy. See here as to why I configured it to call install.

In summary I hope you can see how easy it is to build an executable jar with Maven and to have it released with the correct release tag every time you release your project.

No comments:

Post a Comment