Emulating the Java static class for JavaFX Application

I am trying to create a javaFX Application. Usually this is done as follows:

 Application.launch(classOf[HeadlessWebKit], args: _*)

The issue here is that I want to access the instance of HeadlessWebKit. The OpenFX API does not provide access to the instance. How is this done in Java? We simply declare a static class. Because all members are static I can simply use the static methods and members.

So I tried to declare HeadlessWebKit as:

object HeadlessWebKit extends Application {
}

The problem now is that I get this exception:

Exception in thread "Thread-1" java.lang.RuntimeException: Unable to construct Application instance: class mdocs.HeadlessWebKit$
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:890)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.NoSuchMethodException: mdocs.HeadlessWebKit$.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3349)
	at java.base/java.lang.Class.getConstructor(Class.java:2151)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:801)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
	at 
  ... 

So my first question is: is their any way to generate the init() constructor I need in the object? If not, is their any way I can get the reference of the instantiated class?

TIA

I’m not sure what you mean by “simply declare a static class”. Could you give a code example of how this is done in Java?

@curoli By “simply declare a static class” I mean how can I encode a Java static class in Scala. Or at least compatible with a Java static class. In the case of java HeadlessWebKit, it would be a static class (all members and methods are static). When it is instantiated by JavaFX via its class I get the same “instance”. If I use a Scala class, then a unique instance is generated. One that I cannot access. If I use the object I get the problem I reported previously.

I was thinking of having a shared variable that is updates by the constructor. But is really hacky. I would need to synchronize on that variable too (JavaFX runs in its own thread).

TIA

I have found a solution. Wonder if any Guru could give me feedback on this solution. I did the following:

Created a class that provides me with the <init>() I need:

class  HeadlessWebKit() extends Application {
  override def start(primaryStage: Stage): Unit = HeadlessWebKit.start(primaryStage)
}

Created a singleton of the same class (companion object) with the functionality I need:

object HeadlessWebKit extends Application {
...
}

Created an explicit launcher in the singleton:

  def launchBackground(args: Array[String]): Unit = {
    com.sun.javafx.application.PlatformImpl.startup(() => {
      /* This block will be executed on JavaFX Thread */
    })
    val thread = new Thread {
      override def run() : Unit = {
        Application.launch(classOf[HeadlessWebKit], args: _*)
      }
    }
    thread.start()
  }

Will this blow up on me on later versions of Scala 2? Will this work in Scala 3?

TIA.

Could you show a minimal example in Java that illustrates why you would need what you call a static class, and how you would use it? Cause it is not 100% clear to me. I am pretty sure that Application.launch(...) will always create a new instance, and I don’t really see which problem your solution is solving.

I am just launching a javaFX application via Scala. Here is one Java example and here another here.

The first issue is that we cannot launch Scala JavaFX applications as per the examples in Java. So in Scala we do this. Why? javaFX applications need start the platform first. It can only be done once. In Java the launch methods first initialize the platform, then uses reflection to find the class and instantiates the class. After instantiation it calls the start method.

Usually the above works ok, but I wanted to implement something like this. In other words unlike the standard format I need to have static methods that access a JavaFX application from another thread. I am assuming that static methods are only possible via Scala singletons. So I coded everything as a Singleton. However as per the first message I got an error because no default constructor was found by Java.

What I did was create a HeadlessWebKit class and effectively made the singleton a companion object. Now Java finds the default constructor and initializes the class. It also seems to access the companion object methods correctly.

I just want to make sure that this will not have Java compatibility issues down the line. I have tested with OpenJDK11, Scala 2.12.10 and OpenFX 11.0.2.

Ok, how about something like this?

class HeadlessWebKit extends Application {
  val statics = HeadlessWebKit  // not really necessary but might help for clarity

  // instance methods like start and initialize go here e.g.
  def start(stage: Stage): Unit = { 
    statics.stage = stage
    ...
  }
}

object HeadlessWebkit {
  // all your "static" fields and methods go here
}

Ok. That is close to what I came up with. I have the start in the companion object because I have to share locks (see 4th entry). So correct solution. :sunglasses:

Thank you.