Packaging a .jar as .app file for macOS
When you write a Java application, you’ll get a .jar
file in the end.
If you launch this file in macOS, you’ll end up having the default java icon in the Dock (depending on the application) and you are unable to save the application in the Dock.
It just doesn’t feel right.
To solve this, you can either try to read oracle’s documentation and end up using broken search fields, navigating dead links and outdated stuff until you lay crying in the corner. Or you can just use a Maven plugin which does the work for you.
UPDATE: The Maven plugin I originally used is no longer maintained. I’ve updated the instructions to use another one I found working well.
Possible limitations
I read somewhere that you can’t use the com.apple.eawt
package with this type of app, but it seems to work for me.
For anyone interested, the com.apple.eawt
package is a set of Java extensions for macOS specific applications like handlers for the “Preferences” shortcut and the menubar.
Apple dropped support for this in Java 1.6 (as they stopped developing their own Java version due to security concerns) but there exists a community maintained package which can be used for builds on non-Apple OSes (Java for Mac still contains this package).
The Maven Plugin
You can use the Maven plugin like this:
<plugin>
<groupId>de.perdian.maven.plugins</groupId>
<artifactId>macosappbundler-maven-plugin</artifactId>
<version>1.5.0</version>
<configuration>
<plist>
<CFBundleIconFile>icons.icns</CFBundleIconFile>
<CFBundleDisplayName>My cool app</CFBundleDisplayName>
<CFBundleName>my-cool-app</CFBundleName>
<JVMMainClassName>com.example.myapp.Main</JVMMainClassName>
</plist>
<dmg>
<generate>true</generate>
<autoFallback>true</autoFallback>
</dmg>
<jdk>
<include>true</include>
<location>/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk</location>
</jdk>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
</plugin>
Remember to check if the version supplied above is the current one.
Here’s a quick overview of the config options I think are important:
JVMMainClassName
- This option lets you specify the entrypoint of your application.
- It should point to the class containing your psvm.
jdk > location
- You might not really need this, but if you specify the path to your JRE here, the plugin will bundle it into your
.app
file. - Note that this blows up the application by ~170MB so consider if you really need it.
- You might not really need this, but if you specify the path to your JRE here, the plugin will bundle it into your
CFBundleDisplayName
- This will be the name of your
.app
file. - This will also appear in the
Info.plist
.
- This will be the name of your
CFBundleIconFile
- This option should point to a
.icns
file that will be used for the app. - The path is relative to the location of the
pom.xml
so in the above example,icons.icns
would be in the project root.
- This option should point to a
dmg > generate
- This option will generate a
.dmg
file with your app. - Possible values are:
true
orfalse
(default)
- This option will generate a
The macOS app can be built by running:
mvn clean package
For more information about this plugin and more documentation, go to its GitHub repo.