Simon Kollross

Simon Kollross

Software developer, blogger, elegant code enthusiast.

Packaging a Java app for Mac with Maven

Recently I had the task to prepare a Java app for deployment on MacOS. The project setup was based on Maven and so the packaging step should be integrated in the Maven build process. There were only old and outdated tutorials with lots of manual work out there. Luckily I found a Maven plugin on GitHub, which simplifies this task a lot: https://github.com/federkasten/appbundle-maven-plugin. It supports a lot of configuration options for packaging a Java app and creates a DMG for you. But be careful, the creation of a DMG only works on a Mac.

Basic usage

Insert the following into your build plugins section, customize your main class name and you’re good to go.

<plugin>
    <groupId>sh.tak.appbundler</groupId>
    <artifactId>appbundle-maven-plugin</artifactId>
    <version>1.2.0</version>
    <configuration>
        <mainClass>HelloWorld</mainClass>
        <generateDiskImageFile>true</generateDiskImageFile>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>bundle</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Run clean package appbundle:bundle and after the build finishes you find a DMG in the target folder.

Set icon file and disk name

To set the icon file and the name of the DMG, add this to the <configuration> section:

<bundleName>Hello World</bundleName>
<iconFile>HelloWorld.icns</iconFile>

The icon file requires the .icns format. I used https://iconverticons.com/online/ to generate my icon. You have to add it to src/main/resources because the specified <iconFile> is loaded from this path.

Hint: The <bundleName> is the name of the disk and not the app name! To set an app name you must add <finalName>AppName</finalName> to your <build> section.

Deliver additional files

If you want to deliver additional files with your app which are not packaged into your JAR, add the following to the <configuration> section:

<workingDirectory>$APP_ROOT/../</workingDirectory>
<additionalResources>
    <fileSet>
        <directory>${project.basedir}</directory>
        <includes>
            <include>*.txt</include>
        </includes>
    </fileSet>
</additionalResources>

This snippet selects all .txt files in ${project.basedir} and adds them to the DMG. <workingDirectory> adjusts the working directory of your Java app so you can access the delivered files from within your application as if your app would be a normal JAR without changing file paths in your Java code.

Deliver additional classpath resources

You can deliver classpath ressources for your app, too. These can be e. g. external libs, which are not included in your JAR. Simply add these resources to a folder in your project directory, e. g. dist/libs and include the following:

<additionalClasspath>:$APP_ROOT/../libs/</additionalClasspath>
<additionalResources>
    <fileSet>
        <directory>${project.basedir}/dist</directory>
    </fileSet>
</additionalResources>

Via <additionalClasspath> you can add classpath resources for your app. Hint: Classpathes are separated by a : at the beginning of each referenced directory or JAR file!

I hope you can use some of my code examples for delivering your next Java app for Mac!