I have written a little test application that looks like this:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
public class Test extends Application {
public Test() {
System.out.println("first");
}
#Override
public void init() throws Exception {
System.out.println("second");
super.init();
}
#Override
public void start(Stage primaryStage) throws Exception {
System.out.println("third");
Platform.exit();
}
#Override
public void stop() throws Exception {
System.out.println("fourth");
super.stop();
}
public static void main(String[] args) {
launch(args);
}
}
The output is:
first
second
third
fourth
Now, I am asking myself where the difference is between using the default constructor or the init method for initialising some required things.
Thanks!
P.S.: This question is not duplicate with this one, because my issue does not handle the initialisation of variables. My question is JavaFX specific!
When the Application is launched, the following steps are executed during the launch process:
The instance of the Application subclass that should be launched is created. (Constructor is called)
The init() of that instance is called.
The start method of that instance is called.
See javadoc for Application
Since you exit the application after the start method is called, the stop method of the instance is called.
Note that there is no need to use super.init() and super.stop():
From the javadoc
The init and stop methods have concrete implementations that do nothing.
The differences of constructor, init and start are:
Constructor
If your application is not final the application class could be extended. Since the constructor of the extending class is not complete, it may be dangerous to pass a reference to the class to other classes in this state. Also the instance hasn't been initialized to a point where the getParameters method returns the parameters.
init
Initialisation should generally be done in this method. This method isn't run from the fx application thread, so some things cannot be done from this method, like creating a Stage.
start
Last step in the initialisation. Do things that require to be run from the application thread here. Be careful not to block this thread with long-runing operations however, since this freezes the GUI.
Application Class having init() method which you have override.
The Init method will call immediately after the Test class construction.
Init method is actually an internal method of Application Class. This method is actually initialize the whole FX application components internally.
Application class JavaDoc
it may construct other JavaFX objects in this method.
Related
Right now, I'm considering incorporating 100% code coverage into my project. However, I'm having trouble unit testing the main entry point of my code:
public static void main(String[] args) {
launch(args);
}
This method is difficult to test because it launches an entirely new JavaFX program in the background. In addition to this behavior, a JavaFX program cannot be started more than once. Moreover, the documentation for javafx.application.Application explictly states that, "A JavaFX Application should not attempt to use JavaFX after the FX toolkit has terminated or from a ShutdownHook, that is, after the stop() method returns or System.exit(int) is called."
I am encountering this project because I'm also working with TestFX, a library that helps with clean testing for JavaFX. However, this library does not offer support for the testing of the main method, and as a result I have to write a workaround. There is a possibility of the developers of TestFX knowing about a possible workaround for this problem, for each and every unit tested method, a new instance of an Application is started. Perhaps there could be a way to completely shutdown and reset all variables of a JavaFX program.
To be fair, this method is not that significant to test, however it would be pleasant to have 100% code coverage. It would be entirely reasonable to not test this method as well. The full class can be found below:
package com.meti.app;
import javafx.application.Application;
import javafx.stage.Stage;
/**
* #author SirMathhman
* #version 0.0.0
* #since 4/5/2019
*/ //Main MUST remain public in order for JavaFX Application to start.
public class Main extends Application {
static InfinityImpl implementation = new Infinity();
static Main instance;
#Override
public void start(Stage primaryStage) {
instance = this;
implementation.start(primaryStage);
}
#Override
public void stop() {
implementation.stop();
instance = null;
}
public static void main(String[] args) {
launch(args);
}
}
The static variables above are irrelevant to the aforementioned question and are used for testing purposes in another class which ensures that the delegation works correctly. The application delegates most of the operations to a delegate class which makes the code easier to test.
Moreover, IntelliJ doesn't allow methods to be excluded during code testing.
If you have any other questions, please let me know. Thank you!
Some additional reading:
How to call launch() more than once in java
https://github.com/TestFX/TestFX/blob/master/subprojects/testfx-core/src/main/java/org/testfx/api/FxToolkit.java
What I know till now:
Instance of Servlet is first created by container via reflection and no argument constructor gets used.
Then parameterized init method gets called.
Also it is suggested that we should not create a constructor in servlet class as it is of no use. And I agree with that.
Lets say, I have created a no argument constructor in servlet class and from within that I am calling a parameterized constructor. My question is, will it be called by the container?
public class DemoServlet extends HttpServlet{
public DemoServlet() {
this(1);
}
public DemoServlet(int someParam) {
//Do something with parameter
}
}
Will DemoServlet() be called by the container and if we put some initializing stuff inside it, it will be executed? My guess is yes but it's just a guess based on my understanding.
This might be pretty useless, I am asking out of curiosity.
DemoServlet() will be called (as you are overriding the defined no-arg constructor in HttpServlet (which is a no-op constructor).
However the other DemoServlet(int arg) will not be called.
You are correct with your guess. DemoServlet() would be called by the container and any initialization code within it would be executed - even if that initialization is done through constructor-chaining And as a matter of fact this is a good way to have dependency injection and create a thread-safe servlet which is testable Typically it would be written this way
public class DemoServlet extends HttpServlet
{
private final someParam; //someParam is final once set cannot be changed
//default constructor called by the runtime.
public DemoServlet()
{
//constructor-chained to the paramaterized constructor
this(1);
}
//observe carefully that this paramaterized constructor has only
//package-level visibility. This is useful for being invoked through your
// unit and functional tests which would typically reside within the same
//package. Would also allow your test code to inject required values to
//verify behavior while testing.
DemoServlet(int someParam)
{
this.param = param
}
//... Other class code...
}
How can I get the application instance when using javafx?
Normally you launch an application this way:
public class LoginForm {
public static void main(String[] args) {
LoginApplication.launch(LoginApplication.class, args);
}
}
The method launch does not return an instance of application.
Is there a way I could get the instance?
I was just trying to find an easy, logical way to do exactly this. I haven't. It would be really nice if there was an Application.getApplicationFor(AppClass.class) that managed some singletons for you--but no.
If we restrict the problem space it's pretty easy to solve. If we make the class a singleton, then it's cake... A simplified singleton pattern should work fine:
class MyApp extends Application
{
public static MyApp me;
public MyApp()
{
me=this;
}
...
}
me can be null if it hasn't been instantiated by the system yet. It would be possible to protect against that with more code.
... implementing code...
Just implemented this--seems to work (barring any strange threading situations)
I have a slightly different situation, I'm wedging a javaFX screen into an existing swing GUI. It works fine, but I need to ensure that Application.launch is only called once. Adding this requirement, my final solution is thus:
(Sorry but the syntax has some groovy in it, should be easy for any Java user to translate)
class MyClass extends Application{
private static MyClass instance
public MyClass() {
instance=this
}
public synchronized static getInstance() {
if(!instance) {
Thread.start {
// Have to run in a thread because launch doesn't return
Application.launch(MyClass.class)
}
while(!instance)
Thread.sleep(100)
}
return instance
...
} // class
This manages blocking until Application.launch has completed instantiating the class, getting instances from other locations and ensuring that Application.launch gets called exactly once as long as getInstance has been called at least once.
The problem I'm having is that when I create a new JavaFX project in NetBeans the main method is ignored, and somehow start() is somehow called and everything is just fine, but any time I try to call start I wind up with an exception. The class I used:
public final class JFXDriver extends Application {
public JFXDriver() {
Application.launch();
}
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("GUI.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
I've attempted to start it using the constructor, but it fails (Throws an Exception) for some reason saying that it is being called more than once, which should be impossible because I've constructed this class from a main method with only the new JFXDriver(); in it.
You are doing it wrong in the code. You should not call launch in your constructor. You should call it in your main and pass the name of the class that extends Application.
This causes the system to call init and then start and thus begins the lifecycle of your applicaton. For a more detailed explanation have a look here: http://codelatte.wordpress.com/2013/11/15/getting-started-with-javafx-hello-world-2/
Are you attempting a Swing and FX interop ?
Alright, I've found a solution to the problem. I added:
public static void start() {
Application.launch();
}
and took out the call to Application.launch() in the constructor. This approach worked. I guess that the JavaFX thread created its own instance of the class leading to the Application.launch() being called more than once. Interestingly, without the one application limit, I wonder if this would have led to a StackOverflowException due to the recursive nature of the call.
In my code, I have used :
Application.launch(MyDesign.getClass(), null);
to run a UI of MyDesign from a seperate class.
When it calls launch(), it executes the constructor of MyDesign class. I have created a MyDesign object earlier and initialized its attributes. So I got a new object after calling launch(). I need to stop the calling its constructor when I call
Application.launch().
Your feed back is highly appreciated. Thanks.
Unfortunately you can't directly run already created Application through Application.launch().
You can use next stub application and launch it instead:
public class Runner extends Application {
#Override
public void start(Stage stage) throws Exception {
myDesignInstance.start(stage);
}
}