7

I'd like to create a single Microsoft Installer file for a Java program. I can't use Netbeans or any Maven plugin to do it because I can't use Oracle Java and/or JavaFX (mainly for legal reasons) and both seem to use Oracle native deployment + JavaSE 1.8.

My current archive contains:

  • a Java Runtime Environment (OpenJDK 1.7 JRE)
  • a script (.bat)
  • a fat JAR
  • an icon file
  • a few text files

I don't want to use the JRE of the system, that's why I provide another JRE. The script just calls the JRE with a few arguments. The icon file is in .ico format. The fat JAR is the JAR containing all necessary Java classes, native libraries and assets, including the third party libraries.

I'd like to allow the end user to install, run and uninstall my program. I want to provide one shortcut in the start menu to run it and another one to uninstall it. It seems to be explained here. Do I have to use anything else to create a shortcut to uninstall my program?

I've looked at Wix Toolset for several weeks. I understand that I have to write a wxs file to use with "candle.exe", it creates a wixobj file, I have to run "light.exe" with this file and I get a MSI file.

I know how to add a file, it's explained here but I don't know how to add the whole directory containing the JRE without mentioning each file one by one. How can it be done in the wxs file?

How to pick some unique GUIDs?

Is there already a (more?) simple tool that I can use to make a MSI file from a fat JAR? I prefer understanding how to build such a file in command line under Windows first before trying to do the same programmatically with Apache POI under GNU Linux.

Edit.: This is my first wxs file:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product Id="*" Name="Truly Unusual Experience of Revolution" Language="1033" Version="0.0.0.0" Manufacturer="Julien Gouesse" UpgradeCode="00000000-0000-0000-0000-000000000000">
    <!-- Installer's Icon in Add/Remove Programs -->
 <Icon Id="icon.ico" SourceFile="tuerLogo.ico"/>
    <Property Id="ARPPRODUCTICON" Value="icon.ico" />
 <!-- Installer's version = 200 because the 64-bit support is required -->
    <Package InstallerVersion="200" InstallPrivileges="elevated" InstallScope="perMachine" Compressed="yes" Platform="x64" />
    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
    <MajorUpgrade AllowDowngrades="yes" IgnoreRemoveFailure="yes" Schedule="afterInstallInitialize" />
    <Condition Message="This application is only supported on Windows XP, Windows Vista, Windows Server 2008, or higher.">
      <![CDATA[Installed OR (VersionNT >= 501)]]>
    </Condition>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="APPLICATIONROOTDIRECTORY" Name="Truly Unusual Experience of Revolution">
    <Component Id="tuer.bat" Guid="00000000-0000-0000-0000-000000000000">
            <File Id="tuer.bat" Source="tuer.bat" KeyPath="yes"/>
    </Component>
    <Component Id="tuer.jar" Guid="00000000-0000-0000-0000-000000000000">
            <File Id="tuer.jar" Source="tuer.jar" KeyPath="yes"/>
    </Component>
    <Component Id="LICENSE.txt" Guid="00000000-0000-0000-0000-000000000000">
            <File Id="LICENSE.txt" Source="LICENSE.txt" KeyPath="yes"/>
    </Component>
    <Component Id="NOTICE.txt" Guid="00000000-0000-0000-0000-000000000000">
            <File Id="NOTICE.txt" Source="NOTICE.txt" KeyPath="yes"/>
    </Component>
    <Component Id="README.txt" Guid="00000000-0000-0000-0000-000000000000">
            <File Id="README.txt" Source="README.txt" KeyPath="yes"/>
    </Component>
  </Directory>
      </Directory>
   <Directory Id="ProgramMenuFolder">
        <Directory Id="ApplicationProgramsFolder" Name="Truly Unusual Experience of Revolution"/>
      </Directory>
 </Directory>
 <!-- Shortcut in the Start Menu -->
 <DirectoryRef Id="ApplicationProgramsFolder">
      <Component Id="ApplicationShortcut" Guid="00000000-0000-0000-0000-000000000000">
        <Shortcut Id="ApplicationStartMenuShortcut" 
                  Name="Truly Unusual Experience of Revolution" 
                  Description="First person shooter"
                  Target="[#tuer.bat]"
                  WorkingDirectory="APPLICATIONROOTDIRECTORY"
         Icon="icon.ico" />
          <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
          <RegistryValue Root="HKCU" Key="Software\Microsoft\TrulyUnusualExperienceofRevolution" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
      </Component>
    </DirectoryRef>
    <Feature Id="TrulyUnusualExperienceofRevolution" Title="Truly Unusual Experience of Revolution" Level="1">
   <ComponentRef Id="tuer.bat" />
   <ComponentRef Id="tuer.jar" />
   <ComponentRef Id="LICENSE.txt" />
   <ComponentRef Id="NOTICE.txt" />
   <ComponentRef Id="README.txt" />
   <ComponentRef Id="ApplicationShortcut" />
 </Feature>
  </Product>
</Wix>

Edit.2: This is the file obtained by running "heat" on the JRE directory.

N.B: I don't answer to my own question but I stopped investigating when I discovered that building an installer with NSIS (Nullsoft Scriptable Install System) would be a lot easier because there are already an Ant task and some packages for several GNU Linux distros (including Mageia, Fedora, ...) to make it work. You can find a script called Java Launcher to look for a JRE in your software and in your operating system (even though I advise you to bundle an OpenJDK JRE in your software to ensure that it will go on working despite the updates or the absence of a JRE in the operating system), another script with automatic JRE installation and a rudimentary example of nsi script for a Java based software.

P.S: By the way, I now use my own tool (which uses Redline RPM under the hood), it's fully documented, open source (under GPL), and works for RPM, DEB, APP and EXE (via NSIS) too, it's called Java Native Deployment Toolkit.

gouessej
  • 3,640
  • 3
  • 33
  • 67
  • 1
    Look to "heat.exe" to create components from a source directory tree. GUIDs can usually be generated by "candle", that is, omitted from the source. – Tom Blodget Apr 21 '15 at 03:10
  • Some administrators might reject your JRE and insist on taking responsibility for maintaining their own so they can apply security updates. You could make your JRE an optional feature to enable them to do so. – Tom Blodget Apr 21 '15 at 03:13
  • You're right about some administrators demanding to take the responsibility of the JRE. The private JRE isn't system wide and I can "minimize" it. I can remove most of the useless (to me, in this particular project) parts from it, the Java Plugin, AWT, Swing, JavaFX, ... I don't want to support several JREs, I know the few limitations of OpenJDK. In my humble opinion, Apple JVM is sometimes a nightmare. A smaller JRE without the most problematic parts is safer than the unchanged Oracle Java JRE. It would be tricky but doable to install OpenJDK only when no JRE is available. – gouessej Apr 21 '15 at 08:57
  • @TomBlodget heat dir "my_dir" -template:product -ag -out product.wxs seems to what I want. – gouessej Apr 21 '15 at 10:28
  • @TomBlodget How can I omit the GUIDs from the source? I've just posted my wxs file above, do I have to leave the "Guid" attributes empty? – gouessej Apr 21 '15 at 13:42
  • 1
    Omit the entire attribute. If a consistent GUID cannot be generated (based on the path), candle give an error. – Tom Blodget Apr 22 '15 at 04:47
  • Can you actually give some implementation details? Searching for how to create the GUI for the maven-wix-plugin points to this question. – user1814946 Dec 03 '18 at 22:56
  • @user1814946 Sorry for the late reply but I no longer use Wix. – gouessej Jan 15 '19 at 13:49

4 Answers4

4

Upgrade to Java 14+ and use the built-in jpackage tool (which is the descendant of the 'jpackager' from Jave 8/9). Like most, it generates packages for the system you run it on:

  1. Linux: deb and rpm
  2. macOS: pkg and dmg
  3. Windows: msi and exe

It uses jdeps and jlink to build a minimal JRE to include in the installer, avoiding the need to separately download Java. Plus, it's free with every JDK download. Thanks to Kevin Rushforth and the JEP343 team! Read the development log at https://bugs.openjdk.java.net/browse/JDK-8200758 or do jpackage --help. Note that, as of Java14, it's technically still in "incubation" so some features might change.

idarwin
  • 607
  • 4
  • 19
  • It's a step in the good direction but jpackage is still unable to generate packages for GNU Linux under Windows, Windows executables under GNU Linux, packages for OS X under GNU Linux, etc... unlike my own tool. – gouessej Jul 22 '20 at 13:11
  • 1
    gouessej But you'd have to put a different platform-dependent JRE in for each platform, so wouldn't you have to run the create-app-dir step over again for each platform? Anyway, if it works for you (which it obviously does :-)), then good. – idarwin Jul 22 '20 at 19:45
  • Yes, it's what I do, I use AdoptOpenJDK binary builds, it works like a charm. Supporting OS X is honestly a nightmare with Gatekeeper and its friends... I could benefit of JLink's cross targeting to create a minimal JRE and pass it to JNDT: https://stackoverflow.com/a/47594270/458157 Your suggestion is valuable. If I had much spare time, I'd contribute. – gouessej Jul 23 '20 at 22:11
3

The javapackager from the OpenJDK project for Java 8/9 includes the ability to package MSI installers (using WIX) that include custom JRE installations for the installed application. If you don't wish to use the packager provided with Oracle Java or one that you compile from the OpenJDK source, maybe reviewing the javapackager source code might help you to create your own packaging utilities.

Licensing seems to be a concern for you - so if you adopt this path, you can check that the OpenJDK legal documents are amenable to your situation. Note that if you use OpenJDK, the Oracle BCL is not applicable.

I have not checked the javapackager source in detail, but it may have some reliance on Java 8 features. As your target is to create a JRE 7 based package, you might be able to use a Java 8 runtime to execute the packager, but package a Java 7 JRE as a target. If you must run the packaging tools using a Java 7 runtime and the packager code uses Java 8 features - you could fork it and backport it to Java 7 (you would need some pretty strict requirements to require this - most people would not have such requirements).

I'm not recommending the above as the most ideal way to accomplish your task - I'm just throwing out some ideas which might or might not be useful to you.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • My game is under GPL version 2. The Oracle BCL (Oracle Binary Code License Agreement) for JavaSE and JavaFX is a bit annoying, especially when you want to drop some useless files: http://www.oracle.com/technetwork/java/javase/terms/license/index.html Thank you for the ideas, it's worth a look as the source code is available. – gouessej Apr 21 '15 at 08:49
  • @gouessej Did you read the section about optional files at http://www.oracle.com/technetwork/java/javase/jre-8-readme-2095710.html ? – swpalmer Jan 12 '16 at 20:23
  • Yes I did, it shows that a few files can be legally dropped but it is still less flexible than using OpenJDK which has satisfied me a lot for years in my daily use :) – gouessej Jan 13 '16 at 11:40
1

I run an opensource project called IsWiX that handles this scenario. You can watch a video (linked below) for creating an MSI for a WPF .NET desktop application.

The concepts are the same for a Java application. You just deploy a private instance of the JRE along with your application and create a shortcut that points to the .BAT file. About the only thing you would do custom is create an Icon element that points to your ICO file and set an attribute on the Shortcut element to point to the icon. In the compiled code world we don't have to do this as the shortcut will automatically display the default icon resource in the target executable.

A little write up on the video can be found here:

Building and Deploying a Windows Desktop Application using IsWiX

And the (silent) video itself:

Building and Deploying a Windows Desktop Application using IsWiX

Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
  • I can advise my colleagues to use iswix, it seems to be interesting :) I'll give it a try but I'll have to understand its source code in order to do the same in my own tool: https://svn.code.sf.net/p/tuer/code/pre_beta/jndt.xml Please can you confirm that I can use your software to create a wxs file? I need to understand what is done "under the hood". – gouessej Apr 21 '15 at 09:10
  • 1
    Windows 8.1 shows a scary warning because the application is probably unsigned. I see that "we" have to pay the "toll" so that the lord Microsoft allows our end users to launch our softwares flawlessly :s – gouessej Apr 21 '15 at 09:18
  • 1
    IsWiX is merely a set of visual studio project templates that provides scaffolding and a .NET winforms application that uses Linq to XML to provide visual designers for WiX XML. The WiX XML that is generated doesn't require IswiX to be built. – Christopher Painter Apr 21 '15 at 09:42
  • I see what you mean, I can use IswiX as a visual designer or a WYSIWYG editor to edit my fragment file (wxs) and pass it to "candle.exe" (Wix). It seems to be a good tool for the developers who don't want to write this kind of file by hand. – gouessej Apr 21 '15 at 09:49
  • Fwiw, I never use candle and light directly. I use a WiX feature called Votive which provides Visual Studio integration and MSBuild support. I end up with a solution (.sln) that contains a wix project (.wixproj) which has code files (.wxs). I pass it off to MSBuild / Team Foundation Server and all of the compile details are taken care of for me. Ultimately candle and light are invoked but I don't have to worry about those details. – Christopher Painter Apr 21 '15 at 10:00
  • Actually, I would like to avoid using Visual Studio as my final aim consists in building MSI files even without Windows. Thank you, I saw the words "Votive" several times in the documentation of Wix Toolset and I didn't know what it means. In my case, I have only one wxs file, I keep it simple. By the way, how can I create a component in your software? – gouessej Apr 21 '15 at 10:11
  • All of my tools are built around concepts familiar to a windows / .net ecosystem developer. Microsoft has made Visual Studio Community Edition free to Open Source developers. You only need VS to do the initial project creation. You don't need it to build as MSBuild is now an open source project that ships on its own. I'm sorry but if you have edge case requirements like building on Linux and such I can't support you. MSI is a windows platform technology and that's the core of my expertise. – Christopher Painter Apr 21 '15 at 10:38
  • I understand your position, using Wix (and IswiX) is a first step for me. "write once (anywhere), run anywhere" is a concept familiar to Java developers, that's why building MSI files not under Windows isn't weird to me, I already build .app files for Mac under GNU Linux and RPM/DEB packages for GNU Linux under Windows with JNDT. .NET 4.0 is installed on my machine, I didn't think that VS was mandatory. Thank you for your precious help anyway. – gouessej Apr 21 '15 at 11:18
  • I'm familiar with the concept of write once run anywhere but I don't believe in it. Typically you have a poor user experience on the windows platform. – Christopher Painter Apr 21 '15 at 12:48
  • It's just gratuitous provocation as you come here to answer to a question about Java to disparage its main mantra and my daily job just proves me that numerous end users are ready to pay to get a "poor user experience". – gouessej Dec 10 '15 at 16:52
  • My apologies, my comment was missing a piece. I was really trying to refer to the installation user experience. There are tools such as Flexera (InstallShield) InstallAnywhere that create Java based installers. These installers may work fine on other platforms but they don't perform well on Windows since they aren't Windows Installer based. I've used a number of applications written in Java on Windows that had a very nice user experience. – Christopher Painter Dec 10 '15 at 16:58
  • Ok I couldn't guess that your previous comment was incomplete. Now it makes sense. I don't use InstallAnywhere. I tried IzPack, it's Java based, I find it not that bad and clean but my aim is to build a real MSI. My own tool JNDT (Java based too) works like a charm to target OS X and GNU Linux, it produces native self-contained application bundles (APP, DEB, RPM), it's transparent for the end user. – gouessej Dec 10 '15 at 17:04
  • I'm also confused by the 7 month delay in being offended by my comment. Perhaps you didn't realize it was left by the same person you had previously engaged with? I'll have to look at JNDT, I've never used it. I always try to use the OS native installation services unless they are really horrible. – Christopher Painter Dec 10 '15 at 17:05
  • I preferred not reacting immediately in order to take some time to think about an appropriate answer, I forgot your reply for a few months but I came back here when StackOverflow told me that my question was popular (more than 1000 views). JNDT "just" produces typical native installers except under Windows, they don't look weird, they behave like any other cleanly packaged application. This is a bundle produced by JNDT for OS X: http://sourceforge.net/projects/tuer/files/tuer/tuer-0.0.0/tuer-0.0.0-0.macosx.universal.tar.bz2/download – gouessej Dec 10 '15 at 20:21
  • Now JNDT produces native installers for Windows too :) – gouessej Jan 26 '17 at 16:43
  • Native as in an MSI? Do you have a link? – Christopher Painter Jan 26 '17 at 17:36
  • It's an installer packaged as an executable based on NSIS rather than an MSI. I totally understand that some developers focus on MSI but at the end, I obtain a Windows executable installer which is exactly what I wanted and I find the documentation of NSIS better than the one of MSI. You can test the installers in the Windows section: http://tuer.sourceforge.net/en/play/ The documentation is here: http://tuer.sourceforge.net/en/documentation/#jndt Using MSI makes sense when you really need some features not present in NSIS. – gouessej Jan 26 '17 at 22:06
  • That isn't a native installer for Windows then. you can now stop trolling this old thread. – Christopher Painter Jan 26 '17 at 23:01
1

Just stumbled upon this question. Maybe my two cents can help. I use two maven plugins together:

1) launch4j-maven-plugin (com.akathist.maven.plugins.launch4j) used to wrap the jar inside an exe file. It also allows to specify a minimum java version. That way, you don't have to ship the java version with the msi (which then has to be updated from time to time), but just redirect the user to the java download page (lightweight solution). Launch4J has a bunch of other features, which makes your java application look nicer f.i. a SplashScreen or you can pass startup params, which is nice. That way you can build very custom installers just by setting some properties in the pom.xml

2) wix-maven-plugin (org.bitbucket.joxley) Since we have an exe now we can create a very nice installer, with desktop shortcuts and a "launch now" checkbox at the end of the installation process.

This combination is not the easiest one to implement, but once it is in place you have countless options to build different versions of your software (Evaluation Copy/Pro Version) and to customize your software (e.g. different look and feel of the installer, even attaching a different software licence is possible). With the command line arguments set in the launch4J plugin you can create an app which starts in a certain state or with a certain configuration.

We use the solution in production for several years now.

haferblues
  • 2,155
  • 4
  • 26
  • 39
  • It's an interesting solution but it has one major drawback: it can run only under Windows. – gouessej May 09 '18 at 09:36
  • @gouessej well, the question was about an MSI Windows Installer. Where else do you want to run that? – haferblues May 23 '18 at 22:19
  • The question is about creating a Windows installer but not necessarily under Windows, there is a difference between the platform on which you run the installer and the platform on which you create the installer. I don't want to build my software under Windows. – gouessej May 24 '18 at 16:05
  • @gouessej You are right.I was thinking about the MSI installer file only. For the build script you need indeed a build server running windows. – haferblues May 28 '18 at 13:37
  • For other readers, having a build server running Windows is exactly what I want to avoid. – gouessej Jan 15 '19 at 13:51