You now have a.app folder which could be used to correctly launch your SWT UI on OSX. However, it isn't very practical to distribute a folder so there is one more step to package this up. Step 3 - Package.app Folder. The correct way to do this would be to package the.app folder as an OSX 'Disk Image'. Output directory: we can put here the jar to pack (in our case, we did this), and it’ll also contain the app when it’s created. Name: the name of the app; display name: the name as displayed; identifier: it must match an App ID registered in your Mac Developer account. This registration can be done afterwards, and it’s only necessary if you’re going to distribute in the Mac Store, not for third parties.
Application code, packaged into a set of JAR files, plus any other application resources (data files, native libraries) Copy of the JRE, to be used by this application only. Native launcher for the application, multiple launchers for a single package are supported. Metadata, such as icons. Multiple package formats are possible. Creating a Mac OS X package for a Java application The following article uses options that are available starting with the Professional edition and project type. This tutorial will guide you through the packaging of a Java application into a Mac OS X compliant package.
Overview
Introduction
In this tutorial, we'll walk through basics of using Maven to create projects, compile Java source pre, and package our application as a standalone .jar with dependencies embedded, a Windows .exe, a Mac .app, and a Debian or Ubuntu based .deb package. I'll also mention some common settings and my recommended plugins.
This tutorial assumes you already have the Java 8 JDK installed.
What is Maven?
Maven is a build tool that automates the compiling, dependency management, packaging, and even deployment of Java applications.
Why use Maven instead of compiling with javac?
It's good to know how to compile something manually using javac, but when projects get larger and require third-party libraries, it becomes tedious to manage dependencies and build scripts. Maven offers several benefits:
- Generate pre-built templates for different types of projects
- It's widely used and supported by the Java community and is an Apache project
- Maven manages building the .jar, which requires manifest files and other tedious configuration if done by hand
- Very extensible with many community plugins
- Easy to run on the command line, and supported by all major IDEs.
- Other people can easy load and build your project using Maven
- Install packages to your local repository
- Deploy packages to remote repositories
Here are some of the other cool things it can do for you with optional plugins:
- Generate JavaDoc documentation in HTML format
- Attach source pre to a jar
- Sign your pre using GPG
- Create Windows .exe files and installers
- Create Mac .app files
- Create Debian/Ubuntu based .deb packages
Maven alternatives
Ant
Maven is the sucessor of the Apache Ant build tool. I recommend to learn just enough Ant to run builds from projects that still use it, but not for new projects. It's generally as simple as running ant in the root folder with the build.xml file.
It is similar to the C Make program. Maven can run Ant tasks with the maven-antrun-plugin.Gradle
Gradle is the newest build tool on the block. Android has adopted Gradle as their build tool, but a large portion of projects are still using Maven as well. Gradle has a much more compact syntax, which makes it attractive to many people. Even if you decide to move to Gradle later, it is worth understanding Maven well.
Installing Maven
Installing may not be necessary if your IDE comes with Maven bundled. For example, Maven comes bundled with NetBeans and IntelliJ IDEA. It is also worth noting that in Debian and Ubuntu based distributions you can simply install maven using apt. We will focus on manually installing Maven and using it from the command line in this tutorial.
To install manually, first go to the Maven download page at https://maven.apache.org/download.cgi.
Download the zipped binary package and then unzip it. The bin directory of the unzipped Maven download will contain the primary tool mvn. Add the Maven bin directory to your PATH environment variable. Also set the JAVA_HOME environment variable to the root directory of your JDK.
Verify installation
To make sure it is installed properly, try running Maven from the terminal with:
Generate a new project with Maven using an archetypes
Maven has a concept called archetypes, which are essentially prebuilt project templates that include folder structure and files needed to get started for a specific type of project. There are tons of archetypes out there that come with templates for building things like command line apps, empty projects, gui apps, and web apps. You can generate a new project in interactive mode where you are prompted to answer a series of questions, or by passing in the arguments as command line options. There is at least one archetype worth memorizing and that is the maven-archetype-quickstart. This generates the simplest possible project with one source file ready for us to edit.
It will ask you to answer a few questions.
- groupId - Your namespace. Your website, or commonly a GitHub account. Examples: com.devdungeon, com.github.nanodano
- artifactId - Name of the package within your namespace(groupId). Example: mytools
- version - Your desired version number. Default provided of 1.0-SNAPSHOT
- package - Name of the package for the one generated .java file. Default of groupId provided.
It will create a directory with the name of the artifactId you provided with a skeleton project ready to go. There will be a pom.xml file in the root directory and the pre inside src directory. Inside the src dir you will find a .java file with Hello World pre. This is where you can start coding.
Optionally, if you want to skip the interactive mode, you can provide the command line arguments, like the groupId, artifactId, and version of your project as command line options like this:
The example just above also includes the optional -DinteractiveMode=false flag, which disables the prompt for you to press Y and review the information. Leave interactiveMode set to true if you do want to review the information before it creates the project.
Other simple archetypes
There are a few other archetypes worth mentioning:
- maven-archetype-quickstart - Basic skeleton Java project
- maven-archetype-plugin - Template for building a custom Maven plugin
- maven-archetype-archetype - Template for building your own archetypes
- maven-archetype-webapp - Template for building a simple servlet
Example usage of different archetypes
What is the pom.xml?
After generating a project with mvn archetype:generate there will be a pom.xml file in the root directory of the project. This is the Project Object Model and provides all the configuration for the build. This is the file where you specify what plugins to use and output file names, etc.
Running common Maven goals
Maven has several actions that can be run, named goals. Some are built in, like compile, while others are provided by optional plugins. Here are some of the most important commands you should know. You need to run these commands from the root directory of your project, the directory with the pom.xml file.
Other common settings in the pom.xml
You can also include additional information about your project including but not limited to: description of project, developer contact information, source control info, and licensing information.
Adding external dependencies to your project
To add external dependencies to your project, define a section for dependencies in the pom.xml file like this:
Maven looks for dependencies in your default repository in your home directory in ~/.m2/repository. You can override the path of the local repostiory by modifying your settings.xml file in ~/.m2/repository to add a localRepository tag like this:
You can even set up your settings.xml file to have different profiles that use different repositories and settings for different projects.
If you don't have a dependency or plugin needed when Maven runs a goal, it will automatically try to download it from the central repository. You can even push your own projects to maven central making them available to everyone on the internet.
Maven central is more secure than other central repositories like npm because the namespaces are controlled by owners and all pre is required to be signed with a GPG key that is publicly available. Someone would have to gain control of the repository credentials and the private gpg key to sign pre and push it to the central repo. Signing allows you to verify the pre came from the same author you expect it to.
Read more about the Maven settings.xml file at https://maven.apache.org/settings.html and check out the central repository at https://search.maven.org.
Specify resource directories
Sometimes your application needs to include static resources like images or icons. You can specify special directories for Maven to look for resources. These resources will be packed in to the JAR. The default directory which requires no configuration is src/main/resources/.
To read and write files from the resource directory, you want to use a special function, java.lang.Class.getResource(). Here is a simple example:
If you want to change or add more directories, you can add a configuration in the build section of your pom.xml.
Read more on the official Oracle documentation about Location-independent Access to Resources.
Output effective pom.xml
When you use a very simple pom.xml file with no plugins, it is still loading some plugins by default without you specifying any. For example, the Maven compiler plugin is automatically included, and so is the Maven JAR plugin. Sometimes you want to override the default settings, like changing the compiler source code level or specifying the main class in a JAR.
To see your full effective JAR including all the default settings and plugins, you can print out the 'effective' pom.xml file. This will let you grab the plugin XML so you can customize the configuration in your own pom.
Running a class
If you want to execute a specific class using Maven you can call mvn exec:java with the -Dexec.mainClass option, like this:
This will let you run a class without having to worry about setting all of the class path for project classes and other dependencies. If you want to configure the main class for the packaged JAR, do that by configuring the Maven JAR plugin in your pom.xml
Installing a jar file to local repository manually
Package Jar As Mac App For Windows 10
There is a goal called install-file that will take a jar file and install it to your local repository.You do not need to be inside a project or have a pom.xml in your directory to run this command, all it requires is the jar you want to put in your repository.
Recommended, but optional plugins
Maven is built on a plugin architecture. even the built in commands like compile are still just plugins. you can override default plugin settings or enable third party plugins by creating entries in the project's pom.xml file. Here are some examples of plugins that are worth being familiar with. An example usage of each plugin is provided, but this is where you should put the plugins in the pom.xml:
After setting up these plugins, they will automatically hook in to the appropriate goal. For example, if you set up all of them, then running mvn package will automatically generate the javadoc and source jars, GPG sign your files, create the shaded jar, and package the .exe, .app, and .deb packages.
Maven Compiler Plugin - Specify Java version
Maven Source Plugin - Attach sources as JAR
Maven JavaDoc Plugin - Autogenerate documentation as JAR
Maven GPG Plugin - GPG sign your files
Maven Jar Plugin - Create a JAR file
Maven Shade Plugin - Create a fat/uber/shaded JAR with dependencies
Launch4j Maven Plugin - Create a Windows .exe file
AppBundle Maven Plugin - Create a Mac .app
Debian Maven Plugin - Create a Debian/Ubuntu .deb package
Publish packages to Maven Central Repository
If you want to push your packages or applications to the Maven central repository there are a few steps:
- Register a namespace in Sonatype JIRA
- Package your project with GPG signature, javadoc, license info, etc.
- Use Maven to deploy to the repository
The full process is documented in its own tutorial: Publish Java Packages to Maven Central Repository.
Conclusion
With the knowledge you have now, you should be able to start working on projects confidently with Maven. There is plenty more to learn about Maven since it can be heavily customized and there are lots of plugins available online. Keep learning and refer to some of the links below for further reading.
Helpful Links
- Official Maven documentation - https://maven.apache.org/index.html
- Maven Central repository - https://search.maven.org
- Maven Plugin Developers Centre - https://maven.apache.org/plugin-developers/index.html
In the past two articles you have seen how to customize your Java application so that it looks and feels more like a native Macintosh application when running on Mac OS X without changing the end user experience on other platforms. A combination of runtime properties and coding changes that targeted Mac OS X specific APIs made a big difference to that audience.
Recall that Mac OS X is a melding of two worlds. Hard core UNIX programmers can pop open a Terminal window and write their Java code using vi and compile and run it from the command line. There is, however, the more traditional Mac audience that interacts with their computer through a friendly UI that follows Apple Human Interface guidelines.
In this article, we look at deploying your Java application. The technical geek audience might be happy with running a class with a main()
method from the command line but the wider audience expects a double-clickable icon that looks and acts like every other native application. In this article, we travel from one end of the spectrum to the other to broaden your potential user base.
Although you should 'test everywhere', your build machine may not be a Mac. Fortunately, as you will see, a double-clickable Macintosh application is just a directory with some special contents and a name that ends with .app
. Even on a Windows machine you should be able to modify your build script to package up a Mac-specific version of your application.
Primitive Distributions
Because Mac OS X ships with J2SE 1.4.1 and J2SE 1.3.1, you can distribute your application as class files or jar files and - in theory - your customer could run your application from the Terminal application. We start with these models and quickly move to double-clickable jar files and shell scripts.
For this article, use the Java Sound Demo as the running example. Download and unzip the zip file. Inside the JavaSoundDemo
directory you will find the source files inside of the src
subdirectory, a jar file, audio files, and html files that we will not use.
Raw Class Files
As a developer, you don't think twice about compiling the source files and running the application using the command line. Compiling the eight files in the src
directory generates fifty class files. You can then run the sample application from the command line like this.
java JavaSound
The Java Sound Demo starts up. We haven't customized the application in any way so the menu appears at the top of the JFrame and not where Macintosh users expect. The application looks like this out of the box.
You have done this compile and run step so many times that you hardly think twice about it. Think of the least technical person you know and ask whether they would be likely to follow these steps to run your application if a competing application were easier to install and run.
This example demonstrates two separate areas of usability. Once we got the application up and running it looked good and ran fine. You would not, however, want to distribute an application to an end user this way. You would have to somehow bundle up the fifty class files for easy download and installation. You would then have to provide instructions for running the application using, in the case of Mac OS X, the Terminal application.
Jar Files
If you are going to have to package up the class files for distribution anyways, you may as well produce a jar file. And, if you are going to produce a jar file, it ought to be executable. In the case of the Java Sound Demo, the file JavaSoundDemo.jar
is executable. Because Mac OS X ships with the Jar Launcher application, the end user needs only double click on the jar file and the application will launch.
To make the jar file executable, the manifest must include the name of the Main class file. Unjar JavaSoundDemo.jar
with the command jar xvj JavaSoundDemo.jar
. Here's the file META-INF/MANIFEST.MF
.
Shell Scripts and Helper Applications
For larger or more complicated applications you are likely to have more than one jar file along with resource files. A common strategy for targeting multiple platforms is to include a batch file and a shell script. Choose the non-platform specific download from the NetBeans homepage. Inside of the bin subdirectory you will find applications for running NetBeans on a variety of platforms.
Nochecking for suncc. Nochecking whether cc understands -c and -o together. Cc -Echecking for icc. Refusing to link macos-provided software openssl 1.1.
The shell script runide.sh
can be run from the command line like this.
sh runide.sh -jdkhome /Library/Java/Home
The NetBeans IDE starts up with this decidedly non-Mac OS X look and feel.
You could, of course, modify the shell script to modify this look and feel, but the NetBeans developers decided on a different approach. Even though the typical NetBeans audience member is technically competent, there should be a friendlier way to start the IDE. They have created a native Mac OS X application called NetBeansLauncher
.
The version of NetBeansLauncher
that is included in the generic NetBeans download is a good next step. You will see how the team took it farther in the next section. On a Mac OS X computer you can double click on the macosx_launcher.dmg
file inside of the bin
directory. This is a disk image. Drag the NetBeansLauncher
from the expanded disk image back into the bin
directory. Now double click on the NetBeansLauncher
. The ReadMe file that was also in the disk image provides the following information about usage.
When launched for the first time, NetBeansLauncher needs to find NetBeans root directory. First it looks into NetBeansLauncher.app itself. If it does not find NetBeans root directory there user must specify NetBeans root directory manually.
For this download, the first time the user starts up the NetBeansLauncher
, they need to navigate to the netbeans
directory. After that, double clicking on the NetBeansLauncher
starts up the NetBeans IDE as if it were any other native Mac OS X application.
First Class Mac OS X Applications
If you download the Mac OS X disk image from the NetBeans distribution and mount it you may be surprised at the simplicity of what you find. Unlike the complex structure visible in the other distributions, you will see five files with documentation and a single application. To install, you can move this NetBeansLauncher
application anywhere on your hard drive. Double click on it and the NetBeans IDE starts right up.
This is the experience that is expected on Mac OS X. The package structure and complexity is hidden from the user and they can't accidentally move a file that renders the IDE unusable. In this section we'll look more closely at the package structure and how to create a Mac OS X application whether or not our build machine is a Mac.
Packages in Mac OS X
Consider again the sentence from the NetBeansLauncher
instructions that says in order to locate the NetBeans root directory, 'First it looks into NetBeansLauncher.app itself.' This implies that NetBeansLauncher
is a directory with the name 'NetBeansLauncher.app'. In the mounted disk image, either right click or Ctrl-click on the NetBeansLauncher icon and choose to 'Show Package Contents'.
The structure is the same for all Mac OS X applications. There is a Contents
directory with an XML file named info.plist
, a text file named PkgInfo, a MacOS directory, and a Resources directory. If you don't have a creator code registered with Apple the PkgInfo text file should contain only the following.
If you have a creator code, use it in place of the question marks. Ordinarily the MacOS folder contains a small stub file that launches the Java VM. In this case the NetBeans team has written their own application. We will look more closely at a property list file in the next section. For now, take a look at the contents of the Resources
directory.
You can see the contents of the same netbeans
package inside of the Resources
subdirectory. This is your key to deploying on Mac OS X. Add in the necessary pieces and then just bundle up your ordinary distribution in the appropriate location. If you have a more flexible build process you should also strip out those pieces that aren't needed for the Mac OS X application such as the Windows executables.
If you are interested in digging deeper into the structure of a Mac OS X application, you will find more information in the Apple publication Anatomy of a Bundle.
Creating 'Native' Java Applications on Mac OS X
If you develop on Mac OS X you can use the Jar Bundler
application to turn jar files into Mac OS X applications. Jar Bundler
is distributed with the other developer tools and is located in Developer/Applications/
. Start it, select the 'Classpath and Files' tab and add the file JavaSoundDemo.jar
.
Select the 'Build Information' tab. For 'Main Class', navigate to the JavaSoundDemo.jar
file again and select JavaSound
from the drop down list. This list is populated by any classes in the jar file containing a main()
method. Accept all of the default settings for the options. You can use the default Java application icon or you can create your own. The icon you see below started as a screen shot of the running Java Sound Demo and was transformed into an icon using the IconComposer
application that is also distributed as part of the developer tools.
Mac os 10.7.5 update. Mar 09, 2017 Question: Q: How do I upgrade MAC OS X 10.7.5 to El Capitan today instead of Sierra? Hello, on my Macbook Pro (late 2011) I have missed to upgrade to El Captain, but want to stay with that functionality. My system works at Mac OS X Lion 10.7.5. How can I upgrade to El Captain instead of Sierra? The App Store option fails.
Press 'Create Application' and enter the name 'JavaSoundDemo'. A Mac OS X application is created for you. You can show the package contents of the generated application as before. You can view the property list with Apple's Property List Editor or with any text editor. It is just an XML file with properties stored as name - value pairs.
The Java properties indicate the location of the jar file, the name of the Main class, and the version of the JRE to be used. The other properties include a pointer to the icon file and to the Java application stub file that is the native executable.
Creating Mac OS X Java Applications on Other Platforms
Take a look at the contents of the package that was generated by Jar Bundler
on Mac OS X.
On another platform you need to duplicate this structure. To create an application named 'JavaSoundDemo' on, say, a Windows machine, start by creating a directory and naming it JavaSoundDemo.app
. Next, create a subdirectory named Contents
. Inside of Contents
you will need a MacOS
directory with the JavaAPplicationStub
. You can create the PkgInfo
text file and your Info.plist
can also be generated by hand and should contain the following XML.
You will need a Resources
directory with a Java
subdirectory into which you put the JavaSoundDemo.jar
file. In other words, with the exception of the JavaApplicationStub
and the music.icns
file, everything else can be created on another platform.
If you use Ant you can easily add a target that takes your jar files, images, and other resources and bundles it up as a Mac OS X application bundle that includes the plist file and Java application stub in the appropriate locations. Every time you create a new build you will automatically have your Mac OS X version. You can also find a growing number of Ant tasks that automate some of the steps outlined in this article.
Summary
When it comes time to deploy your Java application, consider the ease of use of your target audience. Even developers appreciate the double clickable version of the NetBeans IDE. Creating a Java application that looks and feels like a native application does not require a lot of extra work and can easily be integrated into your build process even if your build machine runs a different operating system.