Meegh
Meegh

Reputation: 39

JavaFx prevent client to launch application multiple times

I want to prevent client to launch the application multiple times. I thought of implementing Singleton Pattern.

public class MyClass extends Application {

private static MyClass app = null;

private MyClass (){
    super();   
}

public static MyClass getInstance(){
    if(app == null){
    app = new MyClass();
    }
    return app; 
}

@Override
public void start(Stage primaryStage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("FXMLLogin.fxml"));
    Scene scene = new Scene(root);
    scene.setFill(Color.TRANSPARENT);
    primaryStage.initStyle(StageStyle.TRANSPARENT);
    primaryStage.setOpacity(0.95);
    primaryStage.setScene(scene);
    primaryStage.show();
}
public static void main(String[] args) {
    launch(args);
}
}

However, when I run the app, an error shows up:

 Exception in Application constructor
 java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class  authentification.MyClass
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoSuchMethodException: authentification.MyClass.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getConstructor(Class.java:1825)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$7(LauncherImpl.java:818)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
... 1 more
Exception running application authentification.MyClass

Can someone explain me why? and is it the idea of the Singleton is wrong? Thanks

Upvotes: 1

Views: 378

Answers (1)

James_D
James_D

Reputation: 209330

The lifecycle of a JavaFX application is controlled by the Application class. The static Application.launch(...) method starts the application; it does so by creating an instance of the Application class (by default the class from which launch() is called), calling its no-argument constructor. Since your singleton approach makes the no-argument constructor private, the startup process is no longer able to instantiate your Application class, and you get the exception shown.

However, even without this issue, making your application class a singleton would not achieve what you want. The singleton pattern you use here merely ensures that only one instance of the class can exist within any Java Virtual Machine. If the user launches the application a second time, they create a second JVM, which can have its own instance of your singleton.

To ensure only one application can run at a time, you need some OS-level mechanism of locking the application launch. One approach is to start listening on a specific port at startup and closing that connection at shutdown. Since only one application may listen on a given port, this achieves the desired effect. See JavaFX Single Instance Application for an example.

Upvotes: 5

Related Questions