I figured out a workaround:

1. Detect the OS and architecture and set the classifier based on that

2. Use Grape.grab instead of @Grab to download the platform implementation explicitly

3. Use the main method of the Application instead of explicitly calling Application.launch(..) to make the script compile (javafx.application.Application is not available yet due to Grape.grab().

The working script is as follows:

@Grab('org.openjfx:javafx-controls:21.0.6')
@Grab('org.openjfx:javafx-web:21.0.6')
@Grab('org.openjfx:javafx-media:21.0.6')
@Grab('org.openjfx:javafx-swing:21.0.6')
@Grab('se.alipsa:gade:1.0.0-SNAPSHOT')

import se.alipsa.gade.Gade

String os =System.getProperty("os.name")
String arch =System.getProperty("os.arch")
String classifier ="" if (os =="Linux") {
  if (arch =="aarch64") {
    classifier="linux-aarch64" }else {
    classifier ="linux" }
}else if (os =="Mac OS X") {
  if (arch =="aarch64") {
    classifier ="mac-aarch64" }else {
    classifier ="mac" }
}else if (os =="Windows") {
  if (arch =="amd64") {
    classifier ="win" }else {
    classifier ="win-x86" }
}else {
  println"Unknown OS: $os, arch: $arch" System.exit(1)
}
def javafxVersion='21.0.6' 
Grape.grab(group:'org.openjfx',module:'javafx-base',version:"$javafxVersion",classifier:"$classifier")
Grape.grab(group:'org.openjfx',module:'javafx-graphics',version:"$javafxVersion",classifier:"$classifier")
Grape.grab(group:'org.openjfx',module:'javafx-controls',version:"$javafxVersion",classifier:"$classifier")
Grape.grab(group:'org.openjfx',module:'javafx-web',version:"$javafxVersion",classifier:"$classifier")
Grape.grab(group:'org.openjfx',module:'javafx-media',version:"$javafxVersion",classifier:"$classifier")
Grape.grab(group:'org.openjfx',module:'javafx-swing',version:"$javafxVersion",classifier:"$classifier")

Gade.main()

I think @Grab should have been able to handle this for me or am i wrong?

Regards,
Per

On 4/8/25 20:31, Per Nyfelt wrote:
Hi,

I have a javafx application published to a nexus server that I want to launch from a groovy script.

The application has javafx jar defined as compileOnly (provided in maven lingo) so javafx must be added to the classpath.

When i use a full jdk that includes javafx the applicaton works great but for some reason @Grab does not play well with javafx (i have no issues with other dependencies)

The script (called gade.groovy) looks like this:

@Grab('org.openjfx:javafx-controls:21.0.6')
@Grab('org.openjfx:javafx-web:21.0.6')
@Grab('org.openjfx:javafx-media:21.0.6')
@Grab('org.openjfx:javafx-swing:21.0.6')
@Grab('se.alipsa:gade:1.0.0-SNAPSHOT')

import se.alipsa.gade.Gade
import org.openjfx.application.Application

this.class.classLoader.URLs.each { url ->
  if (url.toExternalForm().contains("javafx")) {
    println "URL: $url"
  }
}
Application.launch(Gade.class, [] as String[])

Running it with `groovy gade.groovy` results in

unable to resolve class org.openjfx.application.Application
 @ line 21, column 1.
   import org.openjfx.application.Application

If i remove the Application import and Applicaton.launch lines the output is

URL: file:/home/username/.groovy/grapes/org.openjfx/javafx-swing/jars/javafx-swing-21.0.6.jar URL: file:/home/username/.groovy/grapes/org.openjfx/javafx-graphics/jars/javafx-graphics-21.0.6.jar URL: file:/home/username/.groovy/grapes/org.openjfx/javafx-base/jars/javafx-base-21.0.6.jar URL: file:/home/username/.groovy/grapes/org.openjfx/javafx-media/jars/javafx-media-21.0.6.jar URL: file:/home/username/.groovy/grapes/org.openjfx/javafx-web/jars/javafx-web-21.0.6.jar URL: file:/home/username/.groovy/grapes/org.openjfx/javafx-controls/jars/javafx-controls-21.0.6.jar

When examining the content of e.g. javafx-controls-21.0.6.jar in the grapes cache reveals an essentially empty file (just the META-INF dir) which leads me to believe that the transient classifier platform implementation jars was not fetched properly and added to the classpath.  Does anyone know if there a way to get @Grab to play nicely with javafx?


Regards,

Per

Reply via email to