Reputation: 39
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
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