Building Self Contained Executable Jars - 2 ways

Building an executable jar file is generally pretty simple if you do not want to package any library jars files with in it. You simply have to insert a Main-Class entry into the manifest file that specifies which class has the main method that you want to execute. That should be sufficient for small Java applications where you do not need to use a jarred library however once you need to use one, problems arise.

One approach is to simple just put your external jars in your classpath however, that is only really acceptable if you are not really deploying your application anywhere. Plus having to push support jar files and update classpaths is a pain. A much preferable approach is you wrap everything up into a single jar file.

Now the Java class loader does not know how to load classes that are in a jar inside another jar which means just manipulating the manifest file will not be enough. Fortunately, there is a nifty utility called one-jar that helps us build these self contained executable jar files. Here I am going to show you 2 ways to use it, one using Maven and one using Ant.

Way 1: Maven
Using Maven is by far the easiest approach. You need to add the following to your pom.xml

</plugins>
  <plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
      <execution>
      <configuration>
        <mainClass>com.chrisjordan.examples.HelloWorld</mainClass>
      </configuration>
      <goals>
        <goal>one-jar</goal>
      </goals>
      </execution>
    </executions>
  </plugin>
</plugins>

<pluginRepository>
  <id>onejar-maven-plugin.googlecode.com</id>
  <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>

This Maven extension will literally package all the jar dependencies along with your code into a single executable jar file. Simple use the maven goal install or package to generate it.
mvn install
mvn package

Way 2: Ant
Ant is still a really popular build tool but in order to use one-jar, it requires a little more work.

Step 1: Download one-jar

Step 2: Expand it some where that you can reference easily. It is probably the best if you expand it in your project directory since if you are working in a team and are committing your code to a repository, it will need to be there so others can use it without having to think about it.

Step 3: Create a task in your build.xml file similar to the one below

<property name="one-jar.dist.dir" value="one-jar-ant"/>
<import file="${one-jar.dist.dir}/one-jar-ant-task.xml" optional="true" />
<target name="jar" depends="clean, build, tests">
  <!-- Construct the One-JAR file -->
  <one-jar destfile="${target.dir}/hello-world.jar">
    <manifest>
      <attribute name="One-Jar-Main-Class" value="com.chrisjordan.examples.HelloWorld" />
    </manifest>
    <main>
      <fileset dir="${build.main.dir}"/>
    </main>
    <lib>
      <fileset dir="${target.dir}/lib" includes="*.jar"/>
    </lib>
    <fileset dir="${build.main.res}" includes="**"/>
  </one-jar>
</target>

So as you can see from the above task, there are some gotchas with that using one-jar in ant. You are responsible for the downloading the one-jar package and expanding it in a directory that you reference from your build.xml. As well, you have to specify the jars and property files that you want packaged up.

Now to build your executable jar, you simple have to call ant with the one-jar task you created