openjfx / javafx-maven-plugin

Maven plugin to run JavaFX 11+ applications
Apache License 2.0
372 stars 59 forks source link

Deprecate `jlink` functionality for removal #131

Open abhinayagarwal opened 3 years ago

abhinayagarwal commented 3 years ago

Apache Maven JLink Plugin is now available. It is the official plugin for jlink support.

jlink functionality in javafx-maven-plugin should be deprecated and users should be encouraged to use the official plugin instead.

betanzos commented 3 years ago

The maven-jlink-plugin works in a very different way than this plugin does.

The main problem I have found is the way it discover the modules that will be (by default) added the custom runtime image: "...this is handled automatically by the given dependencies".

This behavior makes it impossible to execute the jlink command on JavaFX applications since non-platform Maven artifacts are trying to be added add as modules (via the --add-modules parameter).

Another problem with this plugin is that, by default, the application base module isn`t added as module to the custom image.

JavaFX applications need a plugin that better fit their requirements (like this one) in order to generate custom runtime images.

Because of this, I think that the javafx-maven-plugin should keep the jlink functionality.

abhinayagarwal commented 3 years ago

Hi @betanzos,

Thanks for taking time to comment on this issue. Your feedback is valuable in understanding the right approach to solve this problem.

... discover the modules that will be (by default) added the custom runtime image: "...this is handled automatically by the given dependencies".

If we let go of how JavaFX Maven artifacts are released, don't you think this is the right approach?

This behavior makes it impossible to execute the jlink command on JavaFX applications since non-platform Maven artifacts are trying to be added add as modules (via the --add-modules parameter).

This is a pain that we are trying to solve. JavaFX Maven artifacts needs a better way to be bundled. The current approach of using empty jars isn't the best solution to the problem.

Another problem with this plugin is that, by default, the application base module isn`t added as module to the custom image.

I have tried the plugin earlier this year and didn't face any such issue. Do you have a sample or configuration file I can try out to get a better idea of the issue?

JavaFX applications need a plugin that better fit their requirements (like this one) in order to generate custom runtime images.

If we bring the Automatic-Module-Name back into the empty jars, then the jlink functionality will stay in the plugin.

betanzos commented 3 years ago

If we let go of how JavaFX Maven artifacts are released, don't you think this is the right approach?

Maybe yes but, strangely, the image that maven-jlink-plugin generates includes more modules than if it is generated with javafx-maven-plugin, including dependencies with runtime scope (see images below). So for a JavaFX application I think is a better idea to add just the dependent modules based on my app's module descriptor.

javafx-maven-plugin image

image

maven-jlink-plugin image

image



JavaFX Maven artifacts needs a better way to be bundled. The current approach of using empty jars isn't the best solution to the problem.

I can agree with this if the modular structure of the framework is not affected, but it is not the case according to this mail.

  1. Instead of 1 module per component, we will have 2 modules (javafx.base.api and javafx.base.platform)
  2. The javafx.base.api, unlike empty jar, will contain all generic Java code
  3. The javafx.base.platform will contain platform-specific native + Java code
  4. Current application declare their module-descriptor as:
module app {
   requires javafx.base;
}
  1. In future this may be changed depending on how we end up wiring these modules together:
module app {
   requires javafx.base [.api or .platform];
}

And all this because an external plugin since with the official JavaFX Maven plugin it work fine.

I think a better approach can be using a Parent POM for our JavaFX Maven applications (like in Spring Boot apps). This POM can use the same mechanism in order to detect the current OS and define all JavaFX artifacts as managed dependencies including the classifier tag. In this way we would only have to specify the needed dependencies in our POM as so far and we could drop out the empty jars.



I have tried the plugin earlier this year and didn't face any such issue. Do you have a sample or configuration file I can try out to get a better idea of the issue?

Of course! I have crated this repository in GitHub called hellofx-modular based in the official example app hellofx.

Over this project you can run the command $ mvn jlink:jlink in order to create the custom image and then see the included modules (the application module is not there)



If we bring the Automatic-Module-Name back into the empty jars, then the jlink functionality will stay in the plugin.

I have tried versions 16 and 17-ea+14 (the last one including the Automatic-Module-Name entry) and the jlink command ends with the errors below (all tests over the hellofx-modular project):

With JavaFX 16 [ERROR] Error: automatic module cannot be used with jlink: javafx.mediaEmpty from file:///D:/tools/maven-repository/org/openjfx/javafx-media/16/javafx-media-16.jar

**With JavaFX 17-ea+18 [ERROR] Error: automatic module cannot be used with jlink: javafx.baseEmpty from file:///D:/tools/maven-repository/org/openjfx/javafx-base/17-ea+14/javafx-base-17-ea+14.jar

abhinayagarwal commented 3 years ago

And all this because an external plugin since with the official JavaFX Maven plugin it work fine.

I would agree that the change wasn't important but I am happy it lead to rekindle the topic of how JavaFX Maven artifacts are bundled :)

As I understand, empty jars with the Automatic-Module-Name in them only exist because we didn't want to introduce new modules for native/platform jars. Kevin is correct to say that platform modules are implementation details and JavaFX users shouldn't 'be exposed to them. This is vital to keep JavaFX usage simple.

There is also behavorial issue b/w Maven vs Gradle which plays a role in empty jars existent and this comment has more information on it. There is not much we can do about this.

The end goal should be to make JavaFX Maven artifacts JPMS compliant which can only happen if we remove the empty jars or convert them into modules.

abhinayagarwal commented 3 years ago

the image that maven-jlink-plugin generates includes more modules than if it is generated with javafx-maven-plugin, including dependencies with runtime scope (see images below)

maven-jlink-plugin seems to have the correct behaviour here, don't you think? If you want to exclude a dependency from being added to the image, it should be declared as <scope>provided</scope>.

betanzos commented 3 years ago

the image that maven-jlink-plugin generates includes more modules than if it is generated with javafx-maven-plugin, including dependencies with runtime scope (see images below)

maven-jlink-plugin seems to have the correct behaviour here, don't you think? If you want to exclude a dependency from being added to the image, it should be declared as <scope>provided</scope>.

Not always. Sometimes I need to have the flexibility to be able to exchange the artifacts I use at runtime.

betanzos commented 3 years ago

And all this because an external plugin since with the official JavaFX Maven plugin it work fine.

I would agree that the change wasn't important but I am happy it lead to rekindle the topic of how JavaFX Maven artifacts are bundled :)

As I understand, empty jars with the Automatic-Module-Name in them only exist because we didn't want to introduce new modules for native/platform jars. Kevin is correct to say that platform modules are implementation details and JavaFX users shouldn't 'be exposed to them. This is vital to keep JavaFX usage simple.

There is also behavorial issue b/w Maven vs Gradle which plays a role in empty jars existent and this comment has more information on it. There is not much we can do about this.

The end goal should be to make JavaFX Maven artifacts JPMS compliant which can only happen if we remove the empty jars or convert them into modules.

I agree 100% with Kevin's point of view, and yours. Keep JavaFX users away from implementation details is the right approach, because of this I disagree to add more modules which change the way we use the framework.

I still think that this plugin (javafx-maven-plugin) jlink functionality must be not removed, at least until JavaFX Maven artifacts are compatible maven-jlink-plugin. However, once this goal is reached, the problem of having to take extra steps to add the application module to the runtime image would persist, and this bothers me a bit.

XakepSDK commented 3 years ago

This plugin builds incorrect jlink image form me. Half of the dependencies are not present and i don't know why. Maven JLink plugin builds correct image, but it doesn't work well because i have to

  1. Depend on JavaFX 17.0.1
  2. run mvn package
  3. Change JavaFX to 17
  4. run mvn jlink:jlink Only in this order.
betanzos commented 3 years ago

Half of the dependencies are not present and i don't know why.

By "dependencies" do you mean Maven dependencies?

XakepSDK commented 3 years ago

It's a multimodule project with many API + Impl modules. I meant Impl modules. I found that all modules are passed to jlink, but manual service binding is impossible. I filled a ticket: https://github.com/openjfx/javafx-maven-plugin/issues/145

I switched to maven jlinker and using this workaround, a bit hacky, but it works:

  1. mvn package -Djavafx.version=17.0.1 <- to compile and package JARs
  2. mvn jlink:jlink -Djavafx.version=17 <- to create jlink image from JARs made in step 1
sgparry commented 1 year ago

Having beaten my head against a brick wall for many days with both plugins,

I am trying to get successful cross build of a JavaFX from windows 10 x64 (build host) to linux aarch64 (target). The application access an H2 database using eclipselink 4.0.1 and H2 JDBC driver. H2 been patched to be modular via moditect.

I find that neither plugin jlink is 100% functional:

Currently, javafx-maven-plugin is much closer to working. If I make a batch file by cribbing it's command line and adding the two service dependencies via --add-module manually, it works.