Reputation: 343
I develop and distribute a Java Swing app that uses Apache Batik and JavaCV. I've updated it through java 1.6, 7 and 8. Installers for macOS, Windows and Linux are built with Javapackager. Java 8 is end of support in Jan '19 and I can't find a solution to package and distribute at Java 11, the new LTS version.
Neither JavaCV or Batik produce modular jars but I have managed to repackage them to the point where I can compile and produce a runnable jar at Java 11, app works fine but I can't package it for distribution. I was planning dropping to Java 10 to use javapackager and bundle the 11 runtime from there but it uses jlink to produce a custom runtime, jlink fails because JavaCV and Batik aren't modular. jdeps won't produce a module-info.class to patch in and make them modular due to unsatisfied references in Batik and JavaCV, even though my app works fine without them.
As a result I'm going to have to leave the code base at Java 8, and ship it even though no longer supported.
I know there's a call to create a replacement for javapackager but that won't be there until way after Java 8 is deprecated. And I'd still need Batik and JavaCV projects to refactor and build modular jars to produce a custom runtime.
Can anyone offer any other solution please? Have I missed something? Thanks.
Upvotes: 9
Views: 7460
Reputation: 2069
Here is a link to a GitHub template showing how to use jlink, jpackage and GitHub Actions to produce a JavaFX app and native macOS, Windows, and Linux installers with a small JVM:
https://github.com/wiverson/maven-jpackage-template
Here is a (WIP) version that uses Swing and an embedded Spring Boot server:
https://github.com/wiverson/desktop-spring-boot
Upvotes: 2
Reputation: 4712
Update: jpackage
is now included since JDK 14. The following answer is still applicable for older JDK versions, though.
I've had the same issue. I wanted to use JDK 11, but according to JDK-8212780 JEP 343 is scheduled for JDK 13, so we'll need to wait a little longer. Packaging "native" self-contained applications under Java 8 - 10 wasn't a problem, since the packager was included (at least in the Oracle JDK).
Today I found out about this email and figured I'd like to give it a try: You can see my sample project on github.com/skymatic/javafx11-test, which I successfully packaged using the back-ported jpackager
from the JDK development branch.
What I did here:
JAVA_HOME
for it to work...)jdeps
to find out the dependency of my non-modular jar and set the --add-modules
parameter to produce a smaller runtime imageOf course it is even easier for modular projects: In this commit to my sample project you can see that I used jpackager
's parameters for the module path and main module instead of the classpath and main class.
Upvotes: 7
Reputation: 343
So the only solution was to write a wrapper app that uses ProcessBuilder to launch the original apps jar.
Advantage in this is that link can be used to produce the minimal required runtime. Place the jar in the bin directory, then use FPM (https://github.com/jordansissel/fpm) to create an installer.
Sample code for the wrapper
package xyz.arwhite.dslauncher;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class DrumScoreLauncher {
public static void main(String[] args) {
String installHome = System.getProperty("java.home");
String installBin = installHome + File.separator + "bin" + File.separator;
System.out.println("Launching Drum Score Editor from "+installHome);
List<String> cmdLine = new ArrayList<String>();
cmdLine.add(installBin + "java");
cmdLine.add("-jar");
cmdLine.add(installBin + "DrumScoreEditor.jar");
for ( int i = 0; i < args.length; i++ )
cmdLine.add(args[i]);
try {
ProcessBuilder p = new ProcessBuilder(cmdLine);
p.inheritIO();
p.start();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Exiting launcher");
}
}
Upvotes: 0