Showing posts with label release. Show all posts
Showing posts with label release. Show all posts

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.

Monday, 19 January 2015

Maven tip: Release Without Deployment

This is how you do a Maven release, as simple as this:

mvn release:prepare
mvn release:perform

This will move you up a version in your code. Say, for example your last released version is 1.2 (meaning the pom.xml on HEAD is on 1.3-SNAPSHOT), by default your release version will be moved to 1.3 and the version on the pom.xml on HEAD will be moved to version 1.4-SNAPSHOT.

A nice feature is that if you use the flag -dryRun=true on either of the above commands you can go through all the steps without any of the files being checked in. It gives you an opportunity to examine the changes to the pom.xml files before you go through with the commit.

To facilitate the release procedure you need to have these lines configured in your highest level pom.xml file.

<scm
  <connection>scm:git:git@github.com:YourRepository.git</connection
  <url>scm:git:git@github.com: com:YourRepository.git</url>
</scm>

By default the code will be built and deployed to a server.  Typically you will want to deploy to Maven Central or to a local Nexus server.  This is done using the releaseProfiles property in the maven-release-plugin.

But this will not always be the case.  If you just want to do a release of the code, to Git for example, and not deploy the code anywhere you need to override the default maven-release-plugin goal property, which by default is set to deploy and set it to install as below:

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