Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 9 compatibility #100

Open
jmerle opened this issue Feb 21, 2018 · 20 comments
Open

Java 9 compatibility #100

jmerle opened this issue Feb 21, 2018 · 20 comments

Comments

@jmerle
Copy link

jmerle commented Feb 21, 2018

fxlauncher does not seem to work with Java 9, due to javax.xml.bind.JAXB being a Java EE API and not being on the classpath anymore in Java 9 (related StackOverflow question).

Error:

Exception in thread "FXLauncher-Thread" java.lang.NoClassDefFoundError: javax/xml/bind/JAXB
        at fxlauncher.AbstractLauncher.syncManifest(AbstractLauncher.java:201)
        at fxlauncher.AbstractLauncher.updateManifest(AbstractLauncher.java:92)
        at fxlauncher.Launcher.lambda$start$0(Launcher.java:137)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXB
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
        at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
        ... 4 more

Steps to reproduce:

  1. Download the demo launcher jar from the demo website.
  2. Download a Java 9 binary (I used JRE 9.0.4)
  3. Run java -jar fxlauncher.jar, where java is the binary you just downloaded, and fxlauncher.jar is the path to the actual launcher file.

The answers on the StackOverflow post suggest to add JAXB as a dependency, but I have no idea how to test fxlauncher on it's own, so I don't know if that works.

@mordechaim
Copy link

mordechaim commented Mar 11, 2018

I've designed i complete new framework which was highly influenced by this project. It is fully Java 9 compatible. In fact you must use Java 9 to use it.

You can find it here.

@jmerle
Copy link
Author

jmerle commented Mar 11, 2018

While it sounds like a cool project, I am not able to switch to a new framework due to all current users using the launcher created by FXLauncher. While I can re-distribute a newer launcher for the people who want to use Java 9 without problems, I can't swap in your alternative because that would break the current launcher. Besides that, I don't want to force users onto Java 9.

There is a Java 9 fix for FXLauncher in #103, but it isn't merged yet.

@jmerle
Copy link
Author

jmerle commented Mar 12, 2018

That might be true, I haven't tested it myself, but the issue still stands. I rather have Java 9 support for FXLauncher (even if it would take a little longer) than ask all my users to re-install using a new launcher.

@mordechaim
Copy link

mordechaim commented Mar 12, 2018 via email

@jmerle
Copy link
Author

jmerle commented Mar 12, 2018

If FXLauncher would support Java 9, I can distribute a new version of the launcher and tell people "Hey, if you want to use Java 9, use this launcher, but if you're fine with Java 8, just keep rocking the current one!". This would be possible because the way of distributing new releases wouldn't change, so auto-updating from the old launcher would still work perfectly fine, as long as the code I write doesn't rely on Java 9.

If I were to swap in your alternative, I could do two things:

  1. Tell everyone to re-install using the new launcher and use Java 9.
  2. Tell everyone to install the new launcher if they want to use Java 9, and deploy using both FXLauncher and your alternative to prevent the current launcher from breaking.

And again, I am not very familiar with Java 9, so what I'm claiming here might not be true, but this is how I think about it at the moment.

@edvin
Copy link
Owner

edvin commented Mar 12, 2018

Hey guys, sorry about the late reply. I'm extremely busy these days, and will be for a few more weeks. I haven't looked at the PR in detail yet, and it seems it might need some adaptation. I think we also need to keep supporting Java 8 for quite some time.

@oparkerj
Copy link

oparkerj commented May 3, 2018

I also need this change. My project is still in development though so it's not a big deal yet.

@edvin
Copy link
Owner

edvin commented May 3, 2018

With the recent announcement that JavaFX will be removed from the JDK, we will not be targeting JDK9, but rather the decoupled JavaFX library once it becomes available.

@ronsmits
Copy link
Collaborator

ronsmits commented Oct 9, 2018

fxlauncher is able to launch more then just javafx applications allthough it was intentionally meant for that. it seems that jaxb will always stay a seperate jar and the json JEP did not make it for java 9.

I propose we make a version that uses a standard property file to initialize fxlauncher and up the major version number.

@mordechaim
Copy link

mordechaim commented Oct 9, 2018 via email

@TravFitz
Copy link

TravFitz commented Oct 9, 2018

The decoupled JavaFX has already been released, Oracle has said that they are going to lean on OpenJFX and help support building that product. Oracle JavaFX should redirect you to the OpenJFX page.

If you add the dependencies in your pom like so to fix the JAXB issue:

<dependency>
        <groupId>javax.xml.bind</groupId>
   	<artifactId>jaxb-api</artifactId>
    	<version>2.4.0-b180830.0359</version>
</dependency>
	<dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.0</version>
   </dependency>

These are both compatible with Java 9/10 and will get you running with JAXB however you will need to package them into the build so that when running the fxlauncher on another computer that it will run fine.

Another issue that I faced was with the internal API that was parsing arguments from the pom to the manifest, to alleviate that I also added a dependency for Jcommander and then I created an Args.java and parsed them through Jcommander.

The last issue I faced was the runAndWait that was from an impl (which of course we lost access to with JDK 9) so to fix that I used this function, which effectively does the same thing.

public static void runAndWait(Runnable action) {
        if (action == null) {
            throw new NullPointerException("action");
        }

        // run synchronously on JavaFX thread
        if (Platform.isFxApplicationThread()) {
            action.run();
            return;
        }

        // queue on JavaFX thread and wait for completion
        final CountDownLatch doneLatch = new CountDownLatch(1);
        Platform.runLater(() -> {
            try {
                action.run();
            } finally {
                doneLatch.countDown();
            }
        });

        try {
            doneLatch.await();
        } catch (InterruptedException e) {
            // ignore exception
        }
    }

As I mentioned in my post the other day I am happy to show you if you are interested, it does work with JDK 9/10 (and theoretically with 11) you may need to tweak a few things to make it a little more generic but they are only minor.

@ronsmits
Copy link
Collaborator

ronsmits commented Oct 9, 2018

A list in a properties file is usually stored as a comma seperated string. The advantage of using a property file over a packaged jaxb implementation is that in the case of a javafx application the javafx jar will be downloaded as a normal dependency. With a jaxb implentation you would have to make a fat (shaded) jar that IMHO defeats the purpose of fxlauncher.

@TravFitz
Copy link

TravFitz commented Oct 9, 2018

I am still using a property file, the Args.java only defines the names that it is searching for in the properties file like this:

package fxlauncher;

import com.beust.jcommander.Parameter;
import java.util.ArrayList;
import java.util.List;

public class Args {
    
    public ArrayList<String> includeExtensions = new ArrayList<>();
    
    @Parameter
    public List<String> parameters = new ArrayList<>();
    
    @Parameter(names = {"--cache-dir","cache-dir"}, description = "Local Source file to save updated files to")
    public String cacheDir;
    
    @Parameter(names = {"--accept-downgrade","accept-downgrade"}, description = "Allow older versions to be downloaded if cached file is newer than server")
    public Boolean acceptDowngrade = false;
    
    @Parameter(names = {"--stop-on-update-errors","stop-on-update-errors"}, description = "Stop the update process if an error is encountered")
    public Boolean stopOnUpdateErrors = true;
    
    @Parameter(names = {"--whats-new","whats-new"}, description = "Used to describe what is new in the updated version")
    public String whatsNew;
    
    @Parameter(names = {"--preload-native-libraries","preload-native-libraries"}, description = "preloaded native libraries")
    public String preloadNativeLibraries;
    
    @Parameter(names = {"--lingering-update-screen","lingering-update-screen"}, description = "lingering update screen")
    public Boolean lingeringUpdateScreen = true;
    
    @Parameter(names = {"--include-extensions"}, description = "All inclusion of files to search and add to update")
    public String includeExtensionsString;
    
    @Parameter(names = {"--parameters"}, description = "Any additional parameters that need to be passed to the launched application")
    public String parameter;
    
    @Parameter(names = {"--update-text"}, description = "The text that is wishing to be displayed on update")
    public String updateText;
    
    @Parameter(names = {"--update-label-style"}, description = "The update-text style to be applied")
    public String updateLabelStyle;
    
    @Parameter(names = {"--wrapper-style"}, description = "Application wrapper style")
    public String wrapperStyle;
}

@TravFitz
Copy link

TravFitz commented Oct 9, 2018

my fully compiled jxlauncher.jar including all dependencies is 42kb

@mordechaim
Copy link

I may be biased, but check out how I solved the JAXB issue in myself here. I made I micro-implementation using the w3c DOM parser.

It works since we know exactly what elements we have, and I don't work with a generic XML file.

@edvin
Copy link
Owner

edvin commented Oct 10, 2018

That's a neat trick, but for 2.0 I think JSON would make more sense :)

@ronsmits
Copy link
Collaborator

However I dont know if json will be part of the standard JDK as it did not make it for jdk9. We could do an intermediate jdk9 release with either the dom3 parser or a property file (property file is less code IMHO) and then if json has made it into the jdk (10?) we can switch to that

As the days are getting shorter and colder, I will start spending more time again at the keyboard.

@mordechaim
Copy link

mordechaim commented Oct 10, 2018 via email

@edvin
Copy link
Owner

edvin commented Oct 11, 2018

JSON support can be included in a couple of small classes. 2.0 will require your users to download a new installer anyways, so backwards compatibility for the manifest is not important :)

@ronsmits
Copy link
Collaborator

ronsmits commented Oct 12, 2018

I have not been able to find a defiinitive stattement that jep 198 has made it or will make it into jdk 11. I dont know if other people have more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants