Often in the life of a developer there is the need to create a windows executable for a Java application that is build and packaged in a Jar file.

The following short example shows how to create an executable Jar first and a windows executable containing vendor information, a nice icon and other stuff afterwards by using a combination of the Maven Shade Plugin and the launch4j Plugin for Maven.

The Application

We’re building a simple swing application here and we’re just rendering a JColorChooser in a JDialog.

hasCode.com launch4j Maven Tutorial 001
Figure 1. Simple Swing Application

And that’s the code ..

package com.hascode.tutorial;

import javax.swing.JColorChooser;
import javax.swing.JDialog;

public class Main extends JDialog {
 private static final long serialVersionUID = 1L;
 private final JColorChooser cc;

 public Main() {
 setSize(800, 600);
 setTitle("hasCode.com launch4j Maven Tutorial");
 cc = new JColorChooser();
 add(cc);
 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 setVisible(true);
 }

 public static void main(final String[] args) {
 new Main();
 }

}

Configuring Maven

We’re using a combination of the Maven shade plugin and a specific variant of the Launch4j Maven Plugin (there are different implementations available) here. Alternatively you could replace the maven shade plugin with the Maven Assembly Plugin but I’m using the first one here I somehow like this one.

The Shade plugin assembles all dependencies into a runnable jar – the transformer adds the Main-Class header to the MANIFEST.MF.

The configuration of the Launch4j maven plugin should be self-explanatory.

For the look I’ve added an application icon in src/main/resources.

My final pom.xml looks like this one:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hascode.tutorial</groupId>
<artifactId>launch4j-maven-sample</artifactId>
<version>0.0.1</version>
<name>hasCode Launch4j Maven Example</name>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.5.1</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.7.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <shadedClassifierName>shaded</shadedClassifierName>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>com.hascode.tutorial.Main</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </plugin>
        <plugin>
            <groupId>com.akathist.maven.plugins.launch4j</groupId>
            <artifactId>launch4j-maven-plugin</artifactId>
            <version>1.5.1</version>
            <executions>
                <execution>
                    <id>l4j-clui</id>
                    <phase>package</phase>
                    <goals>
                        <goal>launch4j</goal>
                    </goals>
                    <configuration>
                        <headerType>gui</headerType>
                        <jar>${project.build.directory}/${artifactId}-${version}-shaded.jar</jar>
                        <outfile>${project.build.directory}/hasCode.exe</outfile>
                        <downloadUrl>http://java.com/download</downloadUrl>
                        <classPath>
                            <mainClass>com.hascode.tutorial.Main</mainClass>
                            <preCp>anything</preCp>
                        </classPath>
                        <icon>src/main/resources/icon/application.ico</icon>
                        <jre>
                            <minVersion>1.6.0</minVersion>
                            <jdkPreference>preferJre</jdkPreference>
                        </jre>
                        <versionInfo>
                            <fileVersion>1.0.0.0</fileVersion>
                            <txtFileVersion>${project.version}</txtFileVersion>
                            <fileDescription>${project.name}</fileDescription>
                            <copyright>2012 hasCode.com</copyright>
                            <productVersion>1.0.0.0</productVersion>
                            <txtProductVersion>1.0.0.0</txtProductVersion>
                            <productName>${project.name}</productName>
                            <companyName>hasCode.com</companyName>
                            <internalName>hasCode</internalName>
                            <originalFilename>hasCode.exe</originalFilename>
                        </versionInfo>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
</project>

Building

Just run mvn package and you should get the desired hasCode.exe in your target directory. Trying to run the executable on a windows system could look like that:

running application
Figure 2. Running the executable on a windows system

Debugging Log4j

It is easy to debug your final application – just start it with the parameter “–l4j-debug” and in the same directory where the exe is located there should appear a file named launch4j.log containing some more or less useful information like this:

CmdLine:    C:\Documents and Settings\User\Desktop\hasCode.exe --l4j-debug
WOW64:        no
Check launcher:     (n/a)
64-bit search:    SOFTWARE\JavaSoft\Java Runtime Environment...
32-bit search:    SOFTWARE\JavaSoft\Java Runtime Environment...
Match:        SOFTWARE\JavaSoft\Java Runtime Environment\1.6
Match:        SOFTWARE\JavaSoft\Java Runtime Environment\1.6.0_33
64-bit search:    SOFTWARE\JavaSoft\Java Development Kit...
32-bit search:    SOFTWARE\JavaSoft\Java Development Kit...
Check launcher:    C:\Program Files\Java\jre6\bin\javaw.exe (OK)
Heap -Xms:    128 MB / 0%, Free: 211 MB, Heap size: 128 MB
Heap -Xmx:    1024 MB / 0%, Free: 211 MB, Heap size: 1024 MB

Tutorial Sources

Please feel free to view and download the complete sources from this tutorial from my GitHub repository – or if you’ve got Git installed just check it out with

git clone https://github.com/hascode/launch4j-maven-example.git