This chapter shows how to use Ant to package Java and JavaFX applications.

Tutorials and Walk-throughsThe Oracle resources can be difficult to navigate. This section is a place for links to tutorials and walk-throughs pertaining to issues that come up in deployment and packaging.

Tutorial: Hello World with Apache AntThe Ant tool is used extensively in the Oracle Deployment Guide. But the section that Oracle provides for using Ant assumes a basic working knowledge of the tool. Apache.org has provided a very good tutorial for getting started.

Packaging Java as a Native Application with a Self-Contained, Custom Runtime: A Manual Walkthrough

INTENDED AUDIENCE:

Java programmers new to modular Java and deployment.

WHAT:

In this walk-through, we will start with a simple Java program ("Pongish") and end with an .exe file that, when downloaded and executed, will launch the Windows Setup and install our program. The Java program that is installed will be self-contained with a runtime customized to hold only the modules needed to run the program. The steps taken will involve command line Java using the Windows cmd.exe console shell, and InnoSetup 5.

With this walk-through example, the resulting setup.exe download file is 21 MB, and the installed program occupies 87.5MB. In comparison, the same program packed with a complete JRE has a setup.exe download file of 40.5 MB and a footprint of 180 MB.

1) Create a file folder for our deployment project on the Desktop. Name it dpproject. We will refer to its absolute address in the following way:

1

c:\...\Desktop\dpproject

where the ellipsis will refer to specifics such as your Windows User file folder.

2) For our application, I'm reusing code from another tutorial which might be described as an "in-progress" Pong. This code, with its multiple packages, classes and use of graphics, should be more helpful than a single-class HelloWorld example. The more involved file structure affects the syntax of several important commands.

In your IDE, create a project (I'm going to call it Pongish) and import these two classes, complete with package structure, and verify that they run.

3B) Create file folder moduleDemo within source. The file folder moduleDemo is going to be our module container to the application source.

3C) Every module container must have a module-info file. Create a text file and name it module-info.java. Save it in the file folder moduleDemo. The .java file should contain the following text:

1 2

modulemoduleDemo {}

Note that the name of our module's file folder matches the name of the class in this code. The body of the code (to be filled in) will be a series of requires and exports statements that make explicit all dependencies between our module and the required Java runtime modules. We will determine them in a future step.

Probably the easiest way to do this is to copy directly from the top package file folder from where your IDE stores the source files for your application.

COMPILE THE MODULE

4A) Because module-info.java is incomplete, attempts to compile the project will fail. We will use information from the error messages to finish writing module-info.java. From within the project folder dpprject, run the following cmd.exe command:

Note that I am using a Windows Environment Variable to specify the location of the Java 9 JDK in order to address javac.exe. You will likely have to create your own environment variable.

[A couple notes on cmd.exe: (1) The cmd.exe program is a standard Windows program that creates a "console" or "shell" within which you can navigate the file system of your PC and issue commands. To invoke it, right-click the Start Menu and select Run. In the Open field, enter cmd and hit OK. This should open a console and place you in a file directory corresponding to your User name. To navigate from there to the project folder, enter the following command: cd Desktop/dpproject

(2) Notice that the fully addressed javac command is enclosed in quotes. This is because my JDK is located in a subfolder of C:\Program Files and cmd.exe interprets the space character between "Program" and "Files" as a delimiter. Enclosed in quotes, the space is interpreted as a character, and this allows cmd.exe to properly locate javac.exe.

(3) Windows now also comes with PowerShell which is similar to cmd. There are some differences between the two. I think you can use either, but I haven't verified PowerShell works with every step of this tutorial.]

The parameter d (<directory>) designates the file folder where the compiled code will be put. Our command creates and places the result in a folder named compiled.

The next section of the command designates the file folder which holds the modular Java source code. Our source code is in the folder source.

The last clause gives the name of the module to be compiled: moduleDemo.

4B) Because we haven't spelled out the module's dependencies, the result will be a listing consisting of many errors. Inspect the start of the output. You should have a something like the following (I've pasted my first three of 22 errors):

This tell us that our module is dependent upon module javafx.graphics.

4C) Add the following requires line to our module-info code block and save:

1 2 3

modulemoduleDemo { requiresjavafx.graphics; }

4D) With the module-info.java update saved, run the compile line again.

Rather remarkably, the compilation now completes without error. A more involved project could easily require multiple iterations. However, sometimes dependencies don't show up at compile time, but come up at run time. Before declaring that our module-info.java is finished, we need to give our compiled code a test run.

4E) Run the following command line to test if our compiled project runs:

The option -p is a shortened form of --module-path. The module we want to run was just compiled into the compiled folder. The option -m is a shortening of --module and the required value is <module>/<mainclass>. A nice little gotcha here is the syntax specifying the module and its main class. Note the direction of the "/" and the use of "." as a separator for the package structure.

4F) When we run our compiled code, we get an error. Inspect the error code. A diagnostic points out a needed exports dependency.

If the Pongish program fails to run, examine both the contents of module-info.java and any typed commands very closely for typos. Small things, like a missing ";" or a inconsistency in capitalization or wrong direction on a slash can be quite enough to cause a modular compilation to fail.

*ONE MORE STEP* FOR COMPILATIONIf your program makes use of resources, such as graphic or audio files, these have to be copied over manually into the compiled folder system. The javac command does not do this for us.

CREATE CUSTOMIZED RUNTIME WITH jlink TOOLIn this step, we take the compiled source and create a distribution folder.

The required --module-path clause points to where the jlink tool will look for modules. We have two arguments:

1

--module-pathcompiled;"%JAVA9_HOME%\jmods"

One argument (compiled) is the file folder location of our compiled application. The other argument, "%JAVA9_HOME%\jmods", is the file location within which the Java 9 JDK that holds the Java language modules.

The required --add-modules clause names the root module for resolution. For our program, moduleDemo is the only module that needs to be named. Its module-info.class, with its list of requirements, will tell jlink which other modules are needed.

The --launcher clause is optional. The syntax we use is the following:

1

--launchercommand=module/main

With the inclusion of this option, two files are created in dist/bin, based on the name "LaunchDemo". These files are named LaunchDemo and LaunchDemo.bat. The first is a Bash script (for Unix), the second is a Batch file (for DOS). We will use LaunchDemo.bat for testing, to verify that our program runs correctly. But we won't actually need either of these files when we configure Inno Setup 5.

The --output option gives the name that will be assigned to the root folder of the files created by jlink. In our command line, we name the folder dist.

5B) Verify that the distribution application works. In the file folder dpproject/dist/bin, along with many .dll files and a few .exe files, will be a file we specified with our --launcher clause: LaunchDemo.bat. Run this file.

The program should run correctly at this point. A console window is opened for the .bat file and suspended while our program runs. We will configure Inno Setup 5 so that there will be no cmd.exe window opened.

PACKAGE WITH INNO SETUP 56A) Run the Inno Setup Wizard to create an .ISS file. This is done by the Start Menu choice Inno Setup Compiler. (Nothing says "I am a Wizard" like the program name "Compiler", yes?)

6B) Check the checkbox for the following when given the option:

1

NewFile > CreateanewscriptfileusingtheScriptWizard

and hit Next for this, and for the "Welcome Screen" that follows.

6C) The "Application Information" screen that comes up next is self-explanatory. The reader can decide what to fill in, and proceed. I am naming the application Pongish and giving it a version number of 0.1.

6D) For "Application Folder", leave in the defaults. If you put Pongish as the name in the previous step, it will appear now as the default Application Folder Name. This will be the folder name created for our application in the Program Files directory.

6E) Under "Application Files" we are asked to enter the executable. Browse to the .../dpproject/dist/bin folder. Select javaw.exe. Why javaw.exe and not java.exe? The reason is that java.exe is a console application, whereas javaw.exe runs in a window and won't cause a console shell to open. Later on, when editing the completed .ISS file, we will provide a Parameters line that will provide the rest of the text needed to run our module.

6F) Leave the checkbox "Allow user to start the application after Setup has finished" checked, and the checkbox for "The application doesn't have a main executable file" unchecked.

6G) For the "Application Shortcuts" tab, leave the settings so that a Start Menu entry and an optional Desktop Shortcut are made.

6H) For the "Application Documentation" section, I am leaving this blank for now. If you have documents ready to go, this is where they would be identified.

6I) For "Languages" I'm leaving in the default "English".

6J) For "Compiler Settings" I recommend using the Browse button to set the "Custom compiler output folder" to our project folder: "C:\...\Desktop\dpproject". With the next options you can take the opportunity to specify a name for the resulting setup file that is generated, and to specify an icon for the setup file, and even to set a password. I am leaving the default name setup. After we run our compilation, the dpproject folder will contain setup.exe.

6K) On "Inno Setup Preprocessor" if possible, the default will create #define compiler directives. I recommend leaving the option checked if available.

6L) After all these screens, go ahead and generate the .iss file. The wizard will create the file and leave it open for further editing.

EDIT THE .iss FILE7A) If Inno Setup is able, the first section of the .iss file will consist of a set of #define statements. These should all be fine, except for one. Change the #define for "MyAppExeName" to the following:

1

#define MyAppExeName"bin\javaw.exe"

If you don't have #define directives, then you will have to make the same change to every reference to javaw.exe in the document, as the {app} variable will point to the root folder, dist.

7B) In the [Setup] tag section, add the following two lines:

1 2

ArchitecturesAllowed=x64ArchitecturesInstallIn64BitMode=x64

These are needed because Inno Setup 5 defaults to 32-bit, but Java 9 on Windows is 64-bit.

7C) In the [Files] tag section, edit the existing line to the following (as a single line):

This line will direct the setup routine to copy the entire contents of dist to the Program Files/Pongish directory. Not every file needs to be brought over during the install. For example, the Bash and Batch files bin\LaunchDemo and bin\LaunchDemo.bat are not needed, nor is bin\java.exe since we only use bin\javaw.exe. There are likely other files that can be omitted, but I haven't figured out which. If you want to save a few KB, you can delete these files from dist before running the compiler.

7D) In the [Icons] section we inline information pertaining to the icons used in the Start Menu and desktop. The two lines should be edited to the following two single lines by adding a Parameters option:

The filename and parameter contents combine to give us the standard command line form for running a modular Java program. If you have no #define satements, then substitute Pongish for {#MyAppName}, and bin\javaw.exe for {#MyAppExeName}.

When no icon is designated to the wizard, the compiler will default to using the icon stored in the javaw.exe file. If you have an .ico file to use, it should be included as the option IconFilename. As an example, if the icon file is pongish.ico, and you have saved it to the top folder, dist, the resulting line for the Start Menu icon would be the following:

If all goes well, the program will first create the setup.exe file and place it in our project folder, then offer to proceed with an install. Go ahead and run the install, then verify the program runs correctly and was installed in the correct location. I'd also then uninstall and then reinstall by clicking on setup.exe. The key test is taking setup.exe to another PC and running it.

Congratulations on reaching the end of this walk-through!

I wish you the best of success with your publishing, and look forward to playing your Java games.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org