Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to package app at Java 11 with non-modular dependencies

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.

like image 526
Hamish258 Avatar asked Nov 29 '18 22:11

Hamish258


2 Answers

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:

  • Created a new HelloWorld project using OpenJDK 11 and OpenJFX 11.
  • Downloaded the packager and invoke it from the Maven build (note it needs to reside with the JDK and you need to set JAVA_HOME for it to work...)
  • Bonus: I used jdeps to find out the dependency of my non-modular jar and set the --add-modules parameter to produce a smaller runtime image

Of 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.

like image 91
Sebastian S Avatar answered Nov 11 '22 12:11

Sebastian S


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

like image 1
Will Iverson Avatar answered Nov 11 '22 13:11

Will Iverson