FibreFoX / javafx-gradle-plugin

Gradle plugin for JavaFX
Apache License 2.0
428 stars 59 forks source link

Java 9 Support #57

Open swpalmer opened 7 years ago

swpalmer commented 7 years ago

To be clear, I have successfully used this plugin with Java 9, but the support is incomplete because of new options related to modularization.

In Java 9 the javapackager tool has an --add-modules option.

In fact if you run the jfxNative task with Java 9 you will see in the output something like this (note the references to modules):

:jfxNative
Putting task artifact state for task ':jfxNative' into context took 0.0 secs.
Executing task ':jfxNative' (up-to-date check took 0.0 secs) due to:
  Task has not declared any outputs.
Adding 'deploy' directory to classpath: src/main/deploy
Creating parameter-map for bundler 'ALL'
Add /Users/scott/dev/MyApplication/build/jfx/app/lib/somelibrary-3.0.3.jar file to application resources.
Add /Users/scott/dev/MyApplication/build/jfx/app/MyApplication-1.0.3.jar file to application resources.
Skipping 'WebStart JNLP Bundler' because of configuration error 'No OutFile Specificed'
Advice to fix: Please specify the name of the JNLP Outut file in 'jnlp.outfile'
Creating app bundle: /Users/scott/dev/MyApplication/build/jfx/native/MyApplication.app
Module jdk.jvmstat does not exist.
Module jdk.management.agent  does not exist.
Module java.management.rmi  does not exist.
Module jdk.vm.ci does not exist.
"Adding modules: [java.rmi, jdk.charsets, java.xml, jdk.xml.dom, java.datatransfer, jdk.httpserver, javafx.base, java.desktop, java.security.sasl, jdk.zipfs, java.base, jdk.crypto.ec, java.sql.rowset, javafx.swing, jdk.jsobject, jdk.sctp, java.smartcardio, jdk.unsupported, jdk.scripting.nashorn, java.security.jgss, java.compiler, javafx.graphics, javafx.fxml, jdk.dynalink, javafx.media, jdk.accessibility, jdk.security.jgss, java.sql, javafx.web, java.logging, java.xml.crypto, jdk.jfr, jdk.packager.services, jdk.net, java.naming, javafx.controls, java.prefs, jdk.naming.rmi, java.management, jdk.jdwp.agent, java.instrument, jdk.management, jdk.security.auth, java.scripting, jdk.naming.dns, jdk.localedata] to runtime image."
outputDir = /Users/scott/dev/MyApplication/build/jfx/native/MyApplication.app/Contents/PlugIns/Java.runtime/Contents/Home
modulePath = [/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/jmods]
addModules = [java.rmi, jdk.charsets, java.xml, jdk.xml.dom, java.datatransfer, jdk.httpserver, javafx.base, java.desktop, java.security.sasl, jdk.zipfs, java.base, jdk.crypto.ec, java.sql.rowset, javafx.swing, jdk.jsobject, jdk.sctp, java.smartcardio, jdk.unsupported, jdk.scripting.nashorn, java.security.jgss, java.compiler, javafx.graphics, javafx.fxml, jdk.dynalink, javafx.media, jdk.accessibility, jdk.security.jgss, java.sql, javafx.web, java.logging, java.xml.crypto, jdk.jfr, jdk.packager.services, jdk.net, java.naming, javafx.controls, java.prefs, jdk.naming.rmi, java.management, jdk.jdwp.agent, java.instrument, jdk.management, jdk.security.auth, java.scripting, jdk.naming.dns, jdk.localedata]
limitModules = []

Those modules seem to have been picked up automatically. My application needs to explicitly add some modules that aren't automatically included though. E.g. java.xml.bind and java.xml.ws

So there needs to be a way to specify additional modules in the jfx configuration, or perhaps as a temporary workaround, just a way to specify additional options to javapackager in a raw form. It could work much like adding compiler options:

tasks.withType(JavaCompile) {
    if (JavaVersion.current().java9Compatible) {
        options.compilerArgs.add '--add-modules'
        options.compilerArgs.add 'java.xml.bind,java.xml.ws'
    }
}

I think it is important to have support for Java 9 early, even if it might need to change. This allows issues to be reported against Java 9 so they can be fixed. If people can't build their projects with Java 9 they won't find out about issues until they are too late to fix for the Java 9 initial release.

FibreFoX commented 7 years ago

I do know this ;) it is a long time ago, that I had JDK9 installed. Will implement this, when JDK9 is official.

EDIT: I will look into this the next week, I need to think about developing with different JDKs ;) so this might take some while ... but shouldn't be that hard to implement

swpalmer commented 7 years ago

You mention "when JDK9 is official". As I hinted at the end of description, I was hoping to build with Java 9-ea. (Java 9 has been feature complete for a while now, so I'm ramping up my testing efforts.) That's also why I mentioned the possibility of a more direct method of adding any arbitrary options. It may allow people to workaround this and future issues. Even if you don't have proper support until JDK 9 is official, perhaps you can point me to some way I could hack this in?

purringpigeon commented 7 years ago

I agree that we need some support since Java 9 has an official release date of July 27, 2017.

Thanks

On Mar 9, 2017, at 8:57 AM, Scott Palmer notifications@github.com wrote:

You mention "when JDK9 is official". As I hinted at the end of description, I was hoping to build with Java 9-ea. (Java 9 has been feature complete for a while now, so I'm ramping up my testing efforts.) That's also why I mentioned the possibility of a more direct method of adding any arbitrary options. It may allow people to workaround this and future issues. Even if you don't have proper support until JDK 9 is official, perhaps you can point me to some way I could hack this in?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

FibreFoX commented 7 years ago

@swpalmer nagging sometimes works ;) I will take a look into this the next days, if you need to fiddle with a local version, just look at the "workers": https://github.com/FibreFoX/javafx-gradle-plugin/tree/master/src/main/java/de/dynamicfiles/projects/gradle/plugins/javafx/tasks/workers

FibreFoX commented 7 years ago

@swpalmer what EA-version are you using?

FibreFoX commented 7 years ago

@purringpigeon @swpalmer This might even already be working, not sure and haven't digged too deep into this. Please try the following:

jfx{
    // ... other stuff ...
    bundleArguments = [
        'add-modules': 'java.xml.bind,java.xml.ws'
    ]
}

There is a lot of new stuff on a new location for parameter-map: https://github.com/teamfx/openjfx-9-dev-rt/blob/master/modules/jdk.packager/src/main/java/jdk/packager/internal/JLinkBundlerHelper.java#L83

Can you try that and report back?

swpalmer commented 7 years ago

Packaging still doesn't work with that. I get errors trying to copy jars into the application bundle, but the build continues and claims to succeed. Looking into the application bundle I can see that my jars are missing. This is from the build log (slightly sanitized for the web):

:jfxNative
The jar lib/MyServer-3.1.3.jar has a main class my.company.myserver.MyServerMain that does not match the declared main my.company.myserver.ui.MyServerAdminApp
Creating app bundle: /Users/scott/dev/MyServerAdminApp/build/jfx/native/My Server Admin.app
Module jdk.jvmstat does not exist.
Module jdk.management.agent  does not exist.
Module java.management.rmi  does not exist.
Module jdk.vm.ci does not exist.
"Adding modules: [java.xml.bind, java.xml.ws, java.rmi, jdk.charsets, java.xml, jdk.xml.dom, java.datatransfer, jdk.httpserver, javafx.base, java.desktop, java.security.sasl, jdk.zipfs, java.base, jdk.crypto.ec, java.sql.rowset, javafx.swing, jdk.jsobject, jdk.sctp, java.smartcardio, jdk.unsupported, jdk.scripting.nashorn, java.security.jgss, java.compiler, javafx.graphics, javafx.fxml, jdk.dynalink, javafx.media, jdk.accessibility, jdk.security.jgss, java.sql, javafx.web, java.logging, java.xml.crypto, jdk.jfr, jdk.packager.services, jdk.net, java.naming, javafx.controls, java.prefs, jdk.naming.rmi, java.management, jdk.jdwp.agent, java.instrument, jdk.management, jdk.security.auth, java.scripting, jdk.naming.dns, jdk.localedata] to runtime image."
outputDir = /Users/scott/dev/MyServerAdminApp/build/jfx/native/My Server Admin.app/Contents/PlugIns/Java.runtime/Contents/Home
modulePath = [/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/jmods]
addModules = [java.xml.bind, java.xml.ws, java.rmi, jdk.charsets, java.xml, jdk.xml.dom, java.datatransfer, jdk.httpserver, javafx.base, java.desktop, java.security.sasl, jdk.zipfs, java.base, jdk.crypto.ec, java.sql.rowset, javafx.swing, jdk.jsobject, jdk.sctp, java.smartcardio, jdk.unsupported, jdk.scripting.nashorn, java.security.jgss, java.compiler, javafx.graphics, javafx.fxml, jdk.dynalink, javafx.media, jdk.accessibility, jdk.security.jgss, java.sql, javafx.web, java.logging, java.xml.crypto, jdk.jfr, jdk.packager.services, jdk.net, java.naming, javafx.controls, java.prefs, jdk.naming.rmi, java.management, jdk.jdwp.agent, java.instrument, jdk.management, jdk.security.auth, java.scripting, jdk.naming.dns, jdk.localedata]
limitModules = []
excludeFileList = .*\.diz
stripNativeCommands = true
userArguments = {}
java.nio.file.NoSuchFileException: /Users/scott/dev/MyServerAdminApp/build/jfx/native/My Server Admin.app/Contents/Java/lib/MyServer-3.1.3.jar
java.nio.file.NoSuchFileException: /Users/scott/dev/MyServerAdminApp/build/jfx/native/My Server Admin.app/Contents/Java/lib/MyServer-3.1.3.jar
        at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
        at java.base/sun.nio.fs.UnixCopyFile.copyFile(UnixCopyFile.java:248)
        at java.base/sun.nio.fs.UnixCopyFile.copy(UnixCopyFile.java:586)
        at java.base/sun.nio.fs.UnixFileSystemProvider.copy(UnixFileSystemProvider.java:254)
        at java.base/java.nio.file.Files.copy(Files.java:1277)
        at jdk.packager/jdk.packager.builders.mac.MacAppImageBuilder.copyClassPathEntries(MacAppImageBuilder.java:457)
        at jdk.packager/jdk.packager.builders.mac.MacAppImageBuilder.prepareApplicationFiles(MacAppImageBuilder.java:387)
        at jdk.packager/jdk.packager.internal.JLinkBundlerHelper.execute(JLinkBundlerHelper.java:352)
        at jdk.packager/com.oracle.tools.packager.mac.MacAppBundler.doBundle(MacAppBundler.java:359)
        at jdk.packager/com.oracle.tools.packager.mac.MacAppBundler.execute(MacAppBundler.java:437)
        at de.dynamicfiles.projects.gradle.plugins.javafx.tasks.workers.JfxNativeWorker.jfxnative(JfxNativeWorker.java:348)
        at de.dynamicfiles.projects.gradle.plugins.javafx.tasks.JfxNativeTask.jfxnative(JfxNativeTask.java:32)
swpalmer commented 7 years ago

Note I am using 9-ea+163. Tried with Gradle 3.4.1 and 3.5-rc-2.

FibreFoX commented 7 years ago

@swpalmer Are you using some IDE for this? Do you know if gradle is already fully compliant with jdk9? On what OS are you using this?

As there are a lot of internal changes, including the places where the packager-classes are, this might take some while and might break compatibility with jdk8 ... will look into this deeply but will take some time (this goes for the javafx-maven-plugin too).

FibreFoX commented 7 years ago

@swpalmer Can you confirm, that it works with the javapackager itself? Coming from the sourcecode, it looks strange how the content inside that .cfg-files is gathered:

        // The main app is required to be a jar, modular or unnamed.
        if (mainJarType == Module.ModuleType.Unknown || mainJarType == Module.ModuleType.ModularJar) {
            if (mainModule != null) {
                out.println("app.mainmodule=" + mainModule); // TODO get app class from main module mainifest.
            }
        }
        else {
            String mainClass = JLinkBundlerHelper.getMainClass(params);

            if (mainJar != null && mainClass != null) {
                // If the app is contained in an unnamed jar then launch it the
                // legacy way and the main class string must be of the format com/foo/Main
                out.println("app.mainclass=" + mainClass.replaceAll("\\.", "/"));
                out.println("app.mainjar=" + mainJar.toPath().getFileName().toString());
            }
        }

The comment jar, modular or unnamed is not reflected inside that IF-condition, maybe "unknown" was wrongly used as "unnamed" .... still trying to understand what is happening, thats why im interested if this already works.

There is a lot of new stuff inside the internals, even the way how I need to load that jdk-classes, not familiar with that new jmod-files (and how to load them or requireing them).

swpalmer commented 7 years ago

It's such a pain right now to build and run on JDK 9 that I'm not sure when I will have the time to sink into this. I'm wondering if part of the issue is that my application is not modular itself? I will respond here if I find anything new.

(OT: Why is there an explicit call to .toString() in that code when printing the mainjar name?)

FibreFoX commented 7 years ago

Regarding the toString: Path.getFileName() it returns a Path ;)

swpalmer commented 7 years ago

So? String concatenation operator automatically appends the equivalent of toString() ... explicitly calling it is redundant.

FibreFoX commented 7 years ago

haha, indeed :D maybe some internal checkstyle-rule or something with static code quality checks

JustGregory-zz commented 7 years ago

@swpalmer regarding JDK 9 already. It seems to be the case that, even after the release of a new JDK version, most people take a while if/when they upgrade JRE/JDK depending on usage. In my case when Java 6 came out and I was making Minecraft mods and I asked someone (casually) if they thought I should build against JDK 6 compatibility, the answer I got was a generic "I dunno, people are mostly Java 4 yet".

Well, if that holds, then even on Java 9 release, people would still be using various builds of Java 6, 7, or 8 for some time. Having JDK 9 support is good and all, I just don't think it needs to be done any sooner than a couple months after 9 is officially released. -- Only my opinion btw.

FibreFoX commented 7 years ago

@JustGregory thats somewhat my own view of the whole jdk9 situation, but the plugin currently works ;) and still need some (spare) time to figure out what is happening.

What bugs me the most, is the taste of the javapackager being unfinished, I'm not that familiar with the new module-concept, especially with maven-plugins and gradle-plugins requiring other dependencies (like how to depend on jdk.packager.jmod).

Inside the maven-plugin, the dependency is loaded via transitive dependencies, but on gradle I choose a different way of loading/manipulating libs inside the classloader.

Has anyone of you a good and up2date reference on how this module-concept works?

JamzTheMan commented 7 years ago
  1. I think the difference is Java upgrades in the past have been more painful and less automated. For our app we had to make several changes in code going to 1.6, 1.7 we had just a couple and none for 1.8. in fact many users were ahead of us on jre installs for 1.7...
swpalmer commented 7 years ago

@JustGregory @FibreFoX There exists a certain chicken and egg problem. We can't move to Java 9 until the tools we use support it, and the tools we use see no motivation to move to Java 9 because nobody is using it yet. My motivate is simple, I want to make sure that my software is ready to take advantage of Java 9. If there are issues with Java 9 that need to be addressed by the JDK team (Java 9 "bugs") that hold back my application taking advantage of other Java 9 features, that sucks. The Java update cycle is rather slow, so I want to be able to run my code on Java 9 as soon as possible so I can report issues. The "next" Java update is already too far away. In many cases there may be API changes required in the Java code and that kind of change needs to be identified very early because it won't change in an update release. At this point it is already too late. Java 9 is beyond the point were any significant changes can happen before it is released. :-( That is why I think it is very important that development tools support new Java versions as soon as possible - far before the release. Because if I can't even build/run on the next version, how am I supposed to report issues with it?

FibreFoX commented 7 years ago

@swpalmer As I'm not in the state of having a full picture of Java 9, so just to clarify: using the bundled javapackager from the JDK, do you get working bundles?

swpalmer commented 7 years ago

@FibreFoX Well that's sort of the problem.. I don't know yet because it means I have to re-write my project build scripts to call javapackager directly (at which point I wouldn't need this plugin). I'm not even certain that the command-line interface of javapackager is complete enough to allow it. I haven't found the time to do figure it all out. I think I have a simpler project somewhere, where I did just that... I remember having to work around all sorts of issues with javapackager including the correct resources. I too don't have a full picture of Java 9... I'm discovering new requirements as I go.

FibreFoX commented 7 years ago

@swpalmer :) okay ... makes me feel a bit less stupid. As far as I understood, not all parts are finished inside the native launcher stuff. Currently I'm a bit too busy with my normal paid work stuff, but will dig into this again when having more time.

You will get informed when I had the chance to make some adjustments to this gradle-plugin.

FibreFoX commented 7 years ago

https://developer.jboss.org/blogs/scott.stark/2017/04/14/critical-deficiencies-in-jigsawjsr-376-java-platform-module-system-ec-member-concerns

I'm very interested in how this will resolve ... Jigsaw is not only a problem for this javafx-build-plugins, but for others too ... and the article kinda reflects my own thoughts about the whole module-concept :/ until there is proper support of gradle/maven, my work on supporting jdk9 will be pending.

SingingBush commented 7 years ago

Gradle 4.1 is now available with support for Java 9 modules and Java 9 itself should be released next month. Could this issue get picked up again

FibreFoX commented 7 years ago

Hi folks,

just wanted you to inform that I'm more active on my spare-time projects again, after some refactoring of the javafx-maven-plugin, there will be some more activity on the gradle-project. Sorry to keep you waiting ;) but as there were no PRs, I suspect you waiting for me to do the code-tinkering.

netzwerg commented 7 years ago

Fyi, I did a test build of my project on OSX: I am not using modules, but observed that jfxNative is no longer creating a .dmg (only a .app which does not launch).

FibreFoX commented 6 years ago

Anyone who is interested of testing the current snapshot-version (8.9.0-SNAPSHOT), should use the following:

buildscript {
    dependencies {
        classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '8.9.0-SNAPSHOT'
    }
    repositories {
        mavenLocal()
        mavenCentral()
        maven { url "https://oss.sonatype.org/content/repositories/snapshots" }

    }
}
apply plugin: 'java'

repositories {
    mavenLocal()
    mavenCentral()
}

apply plugin: 'javafx-gradle-plugin'

It was required to remove some MacOSX-workaround (had to delete it making it compile), but i doubt this feature was used a lot (will wait for feedback on this one). This was compiled using JDK 9, but I hope this does not create any trouble for you.

As there are no special options for setting the new JDK 9 module things, please use the generic bundleArguments built-in hack:

bundleArguments = [
    // "--module-path"
    'module-path': 'PATH_1;PATH_2;PATH_3', // use File.pathSeparator !!! os-dependant

    // "--module"
    'module': 'module1,module2,module3',

    // "--add-modules"
    'add-modules': 'module1,module2,module3',

    // "--limit-modules"
    'limit-modules': 'module1,module2,module3'
]

For all the developers using the runtime: null-hack to disable bundling the JRE, this seems to not being supported (but I just might have missed the corresponding map-parameter for this).

Hoping for your feedback, thanks a lot in advance and sorry for over four month of delay after official JDK 9 release.

FibreFoX commented 6 years ago

No, this currently does NOT work, because the JDK contains some utterly stupid bug, more details at the javafx-maven-plugin project: https://github.com/javafx-maven-plugin/javafx-maven-plugin/issues/287#issuecomment-360599762

EDIT: there is a breaking change inside the windows-bundlers, linux-users and mac-users are still encouraged to check the latest snapshot-version.

FibreFoX commented 6 years ago

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8196547