The sample application in this blog uses FXML for the screen designs and the application logic is implemented in a java class aka "Controller" class.
The base code of the example in this blog is from Oracle's sample "LoginDemo" application. The sample application from Oracle is a desktop standalone application. I have modified it by pushing out the business logic of authentication onto the ejb-tier (an n-tier application with JavaFX as frontend would typically have server-tier/mid-tier as an EJB or an Webservices and a database as back-end).
FXMLFXML is a scriptable, XML-based markup language for constructing a user interface. It provides a convenient alternative to constructing object graphs in XML rather than in java code.
Note: An user interface or"Scene" in JavaFX is an hierarchical object graph,be it in FXML or java.
There is No schema or tag reference of FXML, it is directly derived from the JavaFX classes. Most JavaFX API classes can be used as elements, and most bean properties can be used as attributes. The rules for constructing object graph are the same in FXML as in java code i.e. governed by API documentation.
A FXML file contains XML declaration at the top, followed by import statements for layout components and then hierarchical object graph (see login.fxml );
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="com.incept.SampleController"> <children> <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" /> </children> </AnchorPane>
One advantage of screen design in FXML over java code is that it provides a clean way of separating presentation layer from application logic.
About JavaFX and this applicationThe entry point for a JavaFX applications is the javafx.application.Application class. This class provides application life cycle functions such as launching and stopping application; it also provides a mechanism for Java applications to launch JavaFX GUI components in a threadsafe manner. In our sample application, class demo.MainLauncher extends javafx.application.Application, so it is the starting/launch point of our application. The main() method of demo.MainLauncher launches the application by calling Application.launch(...). At this stage, the JavaFX runtime takes over and does the following, in order:
- Constructs an instance of the specified Application class
- Calls the init() method
- Calls the start(javafx.stage.Stage) method
- Waits for the application to finish, which happens when either of the following occur:
- the application calls Platform.exit()
- the last window has been closed and the implicitExit attribute on Platform is true.
- Calls the stop() method
Note that the start method (of javafx.application.Application) is abstract and must be overridden. The init and stop methods have concrete implementations that do nothing.
Now putting the above in reference of our application, the JavaFX runtime creates an instance of "MainLauncher" class, then calls its init() method and then calls start(Stage primaryStage) method.
The lone argument of the start(..) method is an instance of "javafx.stage.Stage"; this instance is provided by the platform. The Stage class is the top level JavaFX container (a top level window) within which a "Scene" is hosted; the Scene is the GUI with which the user interacts.
A "Scene" is created by loading an FXML file (see replaceSceneContent(..)). The Scene is rendered by associating/setting it in "Stage" [stage.setScene(scene)].
The GUI/Screen can thus be manipulated in JavaFX application by loading appropriate FXML file as the scene and setting it into Stage. The controller corresponding to the FXML file can be obtained by calling FXMLLoader.getController().
Controller and EJBThe controller class contains bindings for layout components and application logic implemented in the action methods.
In the sample application, when the user clicks on "login" button, FX runtime invokes LoginController.processLogin(..) method, the control gets delegated to EJBClient, which does a remote lookup to "LoginFXInterface" and calls loginClicked(..) method to verify credentials. If the remote method returns true, then profile "Scene" is loaded otherwise an error is displayed on the login screen.
Run ProjectSource for the project is available here for download- login and FXML-LoginModDemo
Download source code, unzip locally and and open project in netbeans (Netbeans 7+).
Project "Login" is an ejb project, build and deploy it to local glassfish (4.0+) server.
Project "FXML-LoginModDemo" is JavaFX client, you will need to either add "classes" folder of "Login" or add jar file in classpath.
There are few options available on how to run the project
1) Within Netbeans
Running the project from netbeans is very simple, In project view, right click on project and select "Run". JavaFX runtime will launch MainLauncher.java
2) Standalone "jar"
Running standalone jar requires quite a few glassfish jars to be copied to the class-path. One way to get around copying all the jars is to bundle FX app in a jar and copy the jar file in glassfish installation directory (same level as module and lib) and run it from there.
java -jar FXML-LoginModDemo.jar
3) Standalone ".exe"
To create an .exe. In Netbeans, select project -> properties -> Build -> Deployment and then select "Enable Native Packaging" checkbox and select option "image". Click OK
Right click on project and select "Build Native Package".
Open windows explorer, go to project location and verify that "bundles" folder is created within "<project location>\dist".
Go to <project location>\dist\lib, copy all the jars to <project location>\dist\bundles\FXML-LoginModDemo\app\lib folder; also copy "modules" folder from Glassfish installation location and copy it in app/lib.
To run project, double click on <project location>\dist\bundles\FXML-LoginModDemo\FXML-LoginModDemo.exe