You are on page 1of 51

Getting Started with JavaFX + Database Operations

When I started to work in my current position, one of my task is to do manual operations for
campaign products every week. After the second week, I thought that I have to automate this
task using a GUI based desktop program instead of using some DB scripts manually. Then, I
started to search which solution I should choose. Finally, I ended up my decision with
JavaFX. This is the starting point of my JavaFX journey. In my JavaFX post series, I will try
to describe how to create a JavaFX application, how to use its core components, how to
communicate with DB and so on.
Before starting JavaFX post series, I want to thank Marko Jakob. I learned a lot stuff from
his tutorial series and I suggest that check that tutorial series.
Let’s get started!

What is JavaFX?
It is a next generation GUI toolkit and you can create rich GUI applications with JavaFX.
You can also customize style using CSS and edit them with XML. Also, it includes a drag
and drop design editor that is called as SceneBuilder. It is much easier to design GUIs with
SceneBuilder. You can drag and drop GUI elements and then modify their style with CSS or
edit them with XML. For more details please visit here.

Prerequisites
• Install latest JAVA JDK 8 from here.
• Install IntelliJ, Eclipse or Netbeans IDE (I prefer IntelliJ)
• Install Scene Builder from here.
• Install Oracle Express Edition from here.

Create a JavaFX Project


Open IntelliJ and click File ->> New Project and then click Java FX and click Next button.

1
Type “First_JavaFX_Project” as Project name and set your Project Location as you want
and click Finish button.

2
Thanks to IntelliJ, it automatically creates a JavaFX project structure and put a sample
Hello World code into Main class.

3
We are going to write our code based on MVC (Model-View-Controller) principle. Thus, I
used three (plus one “util” package) packages. These are controller, model, and view. We
should move .fxml files into view package and controller classes in controller package. Also,
I added one extra package and called it as util. It is for utility classes such as DBUtil for
database connection operations. “model” package comprises “model” and
“DataAccessObject” classes. A sample application structure is shown below figure.

Also, we need to set SceneBuilder path. To do this, go to File ->> Settings, type “JavaFX”
in the search bar. Then, copy and paste SceneBuilder path as shown below and click OK.
Also, please check this link.

After setting the SceneBuilder path, go into sample.fxml file and right click, then you will see
“Open in SceneBuilder” option. When you click this option, the selected fxml file will open
in SceneBuilder. You can also check here.

4
We have almost finished our setup. For our first example, we will use Oracle DB and default
HR schema. In second post, we will do some DML (Database Manipulation) operations
such as Create, Read, Update, Delete, Insert, etc. I also explained how to install and use
Oracle Express at the end of this post.
Now, let’s go to our project’s view folder and create EmployeeOperations.fxml and
RootLayout.fxml files manually. To do this, right click your mouse and create a new empty
text file and changed its name as EmployeeOperations.fxml (in next post, I will change its
name as EmployeeView.fxml) . Do the same for the RootLayout.fxml. If you want, you can
do this with SceneBuilder. Finally, in view folder we will have these two .fxml files.

Go to Windows Start and type SceneBuilder and then press Enter, then SceneBuilder will
open.

After that, click “File ->> Open” and open EmployeeOperations.fxml file.

5
Actually, there are two ways to design user interface. One of them is using IntelliJ to
manipulate .fxml file or using SceneBuilder to design the UI. Using SceneBuilder when
creating and designing UI at the first time is much easier and reasonable. I generally use
intelliJ for manipulating UI at later stages.
First, open EmployeeOperations.fxml file and drag and drop Anchor Pane into the middle
pane of SceneBuilder.

Then, if you want you can modify its properties by using right pane.

6
You can use left pane’s Controls section to add TextField, Label, TextArea, and button to
design your UI as shown below. The below figure is the draft version of the UI, not the final
version.

7
You can also group UI elements. Select the UI elements that you want to group then go to
“Arrange > Wrap in” then click the appropriate choice. If elements are vertically listed, then
chose VBox. If they are horizontally listed, then chose HBox.

8
After grouping those elements, you can change spaces of elements by using right pane
Layout section’s Spacing option.

Then, in order to use these components in the code, you should set fx:id values on the right
pane as shown below.

If you want to set prompt text and default text you can use the Properties section on the
right pane. You can change Prompt Text and Text values as shown below.

While designing UI, you can check its status by typing Ctrl + P.

9
For more information about layout design, you should visit here and
https://dzone.com/refcardz/javafx-8-1 (I suggest you to visit DZone. They explained layout
design very well.)
Now, let’s design RootLayout. Open RootLayout.fxml with SceneBuilder.
This time drag and drop BorderPane.

Then, add to MenuBar into TOP slot.

10
RootLayout’s final design is shown below.

Our aim is to show EmployeeOperations.fxml into RootLayout.fxml. Now, I want to


explain JavaFX application structure briefly. Our generated Main class code is shown
below.
package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

11
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("view/sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[fusion_builder_container hundred_percent="yes"
overflow="visible"][fusion_builder_row][fusion_builder_column type="1_1"
background_position="left top" background_color="" border_size="" border_color=""
border_style="solid" spacing="yes" background_image="" background_repeat="no-
repeat" padding="" margin_top="0px" margin_bottom="0px" class="" id=""
animation_type="" animation_speed="0.3" animation_direction="left"
hide_on_mobile="no" center_content="no" min_height="none"][] args) {
launch(args);
}
}

This is the default (generated) Main class and it extends Application class. It has start and
main methods. The key method is here start method. It is automatically called with stage
parameter when application launched as you can see in main method.
As you can see below figure, the main container is Stage and it consists of a scene and
scene comprises all kinds of JavaFX elements such as text field, button, etc. All JavaFX
applications structure is like that. You can find more information here.

If we change main class code as shown below, we can open Employee Operations view
inside of the RootLayout Border Pane. I tried to add comments and make the code more
understandable.
package sample;

import javafx.application.Application;

12
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.io.IOException;

//Main class which extends from Application Class


public class Main extends Application {

//This is our PrimaryStage (It contains everything)


private Stage primaryStage;

//This is the BorderPane of RootLayout


private BorderPane rootLayout;

@Override
public void start(Stage primaryStage) {
//1) Declare a primary stage (Everything will be on this stage)
this.primaryStage = primaryStage;

//Optional: Set a title for primary stage


this.primaryStage.setTitle("SW Test Academy - Sample JavaFX App");

//2) Initialize RootLayout


initRootLayout();

//3) Display the EmployeeOperations View


showEmployeeOperationsView();
}

//Initializes the root layout.


public void initRootLayout() {
try {
//First, load root layout from RootLayout.fxml
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();

//Second, show the scene containing the root layout.


Scene scene = new Scene(rootLayout); //We are sending rootLayout to the
Scene.

13
primaryStage.setScene(scene); //Set the scene in primary stage.

//Third, show the primary stage


primaryStage.show(); //Display the primary stage
} catch (IOException e) {
e.printStackTrace();
}
}

//Shows the employee operations view inside the root layout.


public void showEmployeeOperationsView() {
try {
//First, load EmployeeOperationsView from EmployeeOperations.fxml
FXMLLoader loader = new FXMLLoader();

loader.setLocation(Main.class.getResource("view/EmployeeOperations.fxml"));
AnchorPane employeeOperationsView = (AnchorPane) loader.load();

// Set Employee Operations view into the center of root layout.


rootLayout.setCenter(employeeOperationsView);
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {


launch(args);
}
}

Result:

14
Note: Above UI design is the draft version and in next post, we will change and finalize it. In
this post, I do not want to focus the final design of our UI.
When you click any .fxml file in IntelliJ, you can see its content as shown below.

Before start to coding, I want to explain how to install Oracle Express Database
First, you should visit this link and install Oracle Database Express Edition 11g Release 2.

15
After you installing Oracle Express, please go to this link and UNLOCK HR sample user
account. In this tutorial, we will use HR schema and its tables.
Then, try to connect database with TOAD or Oracle SQL Developer. (I prefer TOAD)
You can see how to connect DB with TOAD in below figure.

16
Now, we are ready to start coding. In next post, we will use DAO (Data Access Object)
Design Pattern and create EmployeeController controller (Business Class), Employee
model (Employee Model), EmployeeDAO (Data Access Class) classes, and DBUtil class
(DB Connection Utility) for DB connection operations.
Sumber: http://www.swtestacademy.com/getting-started-with-javafx/

17
Database Operations in JavaFX
At first, part of JavaFX tutorial series, we created a sample JavaFX project, designed the draft
version of the UI and set up an Oracle XE database. In this post, we will create controller,
model, DAO, and Util classes to do DB operations. Before starting to code, I want to give
more information about our example project. The latest version of the UI is shown in the
figure below.

You can design UI using SceneBuilder. After drag and drop any element to the anchor pane,
you need to set their fx:id properties. These properties must be unique and you can use
elements in your code with their unique fx:id properties. Also, you can copy paste any
element on anchor pane then change its name and fx:id value. I demonstrated how to design a
GUI in the figure below.

18
I listed details of the example below:
• Search an employee using employee’s id and show the result on table view and text area.
(SELECT)
• Search all employees and show them on the table view. (SELECT * FROM)
• Update the e-mail address of an employee by using employee’s id. (UPDATE)
• Delete an employee by using employee’s id. (DELETE)
• Insert a new employee to the “employee table”. (INSERT)
• Show results of all operations on the Text Area (Print on Result Console)
We will use Oracle XE database and its default HR schema. In order to connect Oracle DB,
we will use JDBC driver. JDBC driver is a software component enabling a Java application
to interact with a database. To add JDBC driver in our project:
1) Go to your project, right-click, and then click Open Module Settings.

2) Click Libraries then click “+” sign, click “From Maven”

19
3) Write “odjbc” on search bar and enter. Then, select the “oracle:ojdbc6:11.2.0.3” and
select sources and JavaDocs click OK.

4) Now, we can see ojdbc6:11.2.0.3 library in lib folder on IntelliJ.

20
Finally, we are ready to start coding. As shown the picture below, I created 4 packages:
controller, model, view and util.

I used DAO Design Pattern to perform Employee operations. I want to explain DAO Pattern
briefly, for more information, I suggest that you check Jakop Jenkov’s DAO tutorial. In DAO
pattern, domain (business) logic does not directly communicate with the DB. It
communicates with DAO layer and DAO layer handles DB operations and sends the results to
the business layer.

The philosophy under DAO pattern is that if you need to change the underlying
persistence mechanism, you can do it in DAO layer, not all the places in the business layer.
It is also very important that no details of underlying DB related mechanism leak out of DAO
layer to business layer.

21
DBUtil Class
I want to start to explain the code with DBUtil class. In our example, DBUtil class is
responsible for DB connection, DB disconnection, database query and update operations.
DAO Class (EmployeeDAO) uses DBUtil class’s methods to do higher-level DB operations.
In DBUtil Class:
– dbConnect() method connects to DB.
– dbDisconnect() method closes DB connection.
– dbExecuteQuery(String queryStmt) method executes given SQL statement and returns
cachedRowSet set. In order to eliminate “java.sql.SQLRecoverableException: Closed
Connection: next” error we return cachedRowSet instead of ResultSet. Thus, we can use
cachedRowSet in other classes and manipulate that data.
– dbExecuteUpdate(String sqlStmt) method executes given Update, Insert, Delete SQL
operations.
I tried to write explanatory comments in the code below. If you have questions please don’t
hesitate to write a comment. I will try to answer your questions.
DBUtil Class Code:
package sample.util;

import com.sun.rowset.CachedRowSetImpl;

import java.sql.*;

/**
* Created by ONUR BASKIRT on 22.02.2016.
*/
public class DBUtil {
//Declare JDBC Driver
private static final String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver";

//Connection
private static Connection conn = null;

//Connection String
//String connStr = "jdbc:oracle:thin:Username/Password@IP:Port/SID";
//Username=HR, Password=HR, IP=localhost, IP=1521, SID=xe
private static final String connStr =
"jdbc:oracle:thin:HR/HR@localhost:1521/xe";

//Connect to DB
public static void dbConnect() throws SQLException, ClassNotFoundException {
//Setting Oracle JDBC Driver

22
try {
Class.forName(JDBC_DRIVER);
} catch (ClassNotFoundException e) {
System.out.println("Where is your Oracle JDBC Driver?");
e.printStackTrace();
throw e;
}

System.out.println("Oracle JDBC Driver Registered!");

//Establish the Oracle Connection using Connection String


try {
conn = DriverManager.getConnection(connStr);
} catch (SQLException e) {
System.out.println("Connection Failed! Check output console" + e);
e.printStackTrace();
throw e;
}
}

//Close Connection
public static void dbDisconnect() throws SQLException {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (Exception e){
throw e;
}
}

//DB Execute Query Operation


public static ResultSet dbExecuteQuery(String queryStmt) throws SQLException,
ClassNotFoundException {
//Declare statement, resultSet and CachedResultSet as null
Statement stmt = null;
ResultSet resultSet = null;
CachedRowSetImpl crs = null;
try {
//Connect to DB (Establish Oracle Connection)
dbConnect();
System.out.println("Select statement: " + queryStmt + "\n");

23
//Create statement
stmt = conn.createStatement();

//Execute select (query) operation


resultSet = stmt.executeQuery(queryStmt);

//CachedRowSet Implementation
//In order to prevent "java.sql.SQLRecoverableException: Closed
Connection: next" error
//We are using CachedRowSet
crs = new CachedRowSetImpl();
crs.populate(resultSet);
} catch (SQLException e) {
System.out.println("Problem occurred at executeQuery operation : " +
e);
throw e;
} finally {
if (resultSet != null) {
//Close resultSet
resultSet.close();
}
if (stmt != null) {
//Close Statement
stmt.close();
}
//Close connection
dbDisconnect();
}
//Return CachedRowSet
return crs;
}

//DB Execute Update (For Update/Insert/Delete) Operation


public static void dbExecuteUpdate(String sqlStmt) throws SQLException,
ClassNotFoundException {
//Declare statement as null
Statement stmt = null;
try {
//Connect to DB (Establish Oracle Connection)
dbConnect();
//Create Statement
stmt = conn.createStatement();
//Run executeUpdate operation with given sql statement
stmt.executeUpdate(sqlStmt);

24
} catch (SQLException e) {
System.out.println("Problem occurred at executeUpdate operation : " +
e);
throw e;
} finally {
if (stmt != null) {
//Close statement
stmt.close();
}
//Close connection
dbDisconnect();
}
}
}

Employee Class (Model)


We need a model class to hold information about the employee. Add a new class to the model
package and called it Employee.

This class holds all fields of the Employee such as name, last name, email, etc. It contains set
and get methods and properties for all fields of a model class. A Property notifies us when
any variable such as name, last name, etc. is changed. This helps us keep the view in sync
with the data.
You can see the all fields of the employee from database as shown below.

Employee Class Code:


package sample.model;

import javafx.beans.property.*;

import java.sql.Date;

25
/**

* Created by ONUR BASKIRT on 27.02.2016.

*/

public class Employee {

//Declare Employees Table Columns

private IntegerProperty employee_id;

private StringProperty first_name;

private StringProperty last_name;

private StringProperty email;

private StringProperty phone_number;

private SimpleObjectProperty<Date> hire_date;

private StringProperty job_id;

private IntegerProperty salary;

private DoubleProperty commission_pct;

private IntegerProperty manager_id;

private IntegerProperty department_id;

//Constructor

public Employee() {

this.employee_id = new SimpleIntegerProperty();

this.first_name = new SimpleStringProperty();

this.last_name = new SimpleStringProperty();

this.email = new SimpleStringProperty();

this.phone_number = new SimpleStringProperty();

this.hire_date = new SimpleObjectProperty<>();

this.job_id = new SimpleStringProperty();

this.salary = new SimpleIntegerProperty();

this.commission_pct = new SimpleDoubleProperty();

this.manager_id = new SimpleIntegerProperty();

this.department_id = new SimpleIntegerProperty();

26
}

//employee_id

public int getEmployeeId() {

return employee_id.get();

public void setEmployeeId(int employeeId){

this.employee_id.set(employeeId);

public IntegerProperty employeeIdProperty(){

return employee_id;

//first_name

public String getFirstName () {

return first_name.get();

public void setFirstName(String firstName){

this.first_name.set(firstName);

public StringProperty firstNameProperty() {

return first_name;

//last_name

public String getLastName () {

return last_name.get();

27
}

public void setLastName(String lastName){

this.last_name.set(lastName);

public StringProperty lastNameProperty() {

return last_name;

//email

public String getEmail () {

return email.get();

public void setEmail (String email){

this.email.set(email);

public StringProperty emailProperty() {

return email;

//phone_number

public String getPhoneNumber () {

return phone_number.get();

public void setPhoneNumber (String phoneNumber){

this.phone_number.set(phoneNumber);

28
public StringProperty phoneNumberProperty() {

return phone_number;

//hire_date

public Object getHireDate(){

return hire_date.get();

public void setHireDate(Date hireDate){

this.hire_date.set(hireDate);

public SimpleObjectProperty<Date> hireDateProperty(){

return hire_date;

//job_id

public String getJobId () {

return job_id.get();

public void setJobId (String jobId){

this.job_id.set(jobId);

public StringProperty jobIdProperty() {

return job_id;

29
//salary

public int getSalary() {

return salary.get();

public void setSalary(int salary){

this.salary.set(salary);

public IntegerProperty salaryProperty(){

return salary;

//commission_pct

public double getCommissionPct() {

return commission_pct.get();

public void setCommissionPct(double commissionPct){

this.commission_pct.set(commissionPct);

public DoubleProperty commissionPctProperty(){

return commission_pct;

//manager_id

public int getManagerId() {

return manager_id.get();

30
public void setManagerId(int managerId){

this.manager_id.set(managerId);

public IntegerProperty managerIdProperty(){

return manager_id;

//department_id

public int getDepartmanId() {

return department_id.get();

public void setDepartmantId(int departmentId){

this.manager_id.set(departmentId);

public IntegerProperty departmentIdProperty(){

return department_id;

Employee DAO Class (Data Access Object)


Employee DAO class handles employee related database operations such as searching,
deleting, updating employee with declared SQL statements.
JavaFX view classes need to be informed about any changes made to the list of employees. It
is important for the view to be synchronized with the data. For this purpose, we use
ObservableList collection and hold the employee in this list.
• searchEmployee and searchEmployees methods use DBUtil class’s dbExecuteQuery()
method.
• The other methods (update/delete/insert), use DBUtil class’s dbExecuteUpdate() method.
I tried to add descriptive inline comments in the code shown below.

31
EmployeeDAO Class Code:
package sample.model;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import sample.util.DBUtil;

import java.sql.ResultSet;
import java.sql.SQLException;

public class EmployeeDAO {

//*******************************
//SELECT an Employee
//*******************************
public static Employee searchEmployee (String empId) throws SQLException,
ClassNotFoundException {
//Declare a SELECT statement
String selectStmt = "SELECT * FROM employees WHERE employee_id="+empId;

//Execute SELECT statement


try {
//Get ResultSet from dbExecuteQuery method
ResultSet rsEmp = DBUtil.dbExecuteQuery(selectStmt);

//Send ResultSet to the getEmployeeFromResultSet method and get employee object


Employee employee = getEmployeeFromResultSet(rsEmp);

//Return employee object


return employee;
} catch (SQLException e) {
System.out.println("While searching an employee with " + empId + " id, an error occurred: " +
e);
//Return exception
throw e;
}
}

32
//Use ResultSet from DB as parameter and set Employee Object's attributes and return employee
object.
private static Employee getEmployeeFromResultSet(ResultSet rs) throws SQLException
{
Employee emp = null;
if (rs.next()) {
emp = new Employee();
emp.setEmployeeId(rs.getInt("EMPLOYEE_ID"));
emp.setFirstName(rs.getString("FIRST_NAME"));
emp.setLastName(rs.getString("LAST_NAME"));
emp.setEmail(rs.getString("EMAIL"));
emp.setPhoneNumber(rs.getString("PHONE_NUMBER"));
emp.setHireDate(rs.getDate("HIRE_DATE"));
emp.setJobId(rs.getString("JOB_ID"));
emp.setSalary(rs.getInt("SALARY"));
emp.setCommissionPct(rs.getDouble("COMMISSION_PCT"));
emp.setManagerId(rs.getInt("MANAGER_ID"));
emp.setDepartmantId(rs.getInt("DEPARTMENT_ID"));
}
return emp;
}

//*******************************
//SELECT Employees
//*******************************
public static ObservableList<Employee> searchEmployees () throws SQLException,
ClassNotFoundException {
//Declare a SELECT statement
String selectStmt = "SELECT * FROM employees";

//Execute SELECT statement


try {
//Get ResultSet from dbExecuteQuery method
ResultSet rsEmps = DBUtil.dbExecuteQuery(selectStmt);

33
//Send ResultSet to the getEmployeeList method and get employee object
ObservableList<Employee> empList = getEmployeeList(rsEmps);

//Return employee object


return empList;
} catch (SQLException e) {
System.out.println("SQL select operation has been failed: " + e);
//Return exception
throw e;
}
}

//Select * from employees operation


private static ObservableList<Employee> getEmployeeList(ResultSet rs) throws SQLException,
ClassNotFoundException {
//Declare a observable List which comprises of Employee objects
ObservableList<Employee> empList = FXCollections.observableArrayList();

while (rs.next()) {
Employee emp = new Employee();
emp.setEmployeeId(rs.getInt("EMPLOYEE_ID"));
emp.setFirstName(rs.getString("FIRST_NAME"));
emp.setLastName(rs.getString("LAST_NAME"));
emp.setEmail(rs.getString("EMAIL"));
emp.setPhoneNumber(rs.getString("PHONE_NUMBER"));
emp.setHireDate(rs.getDate("HIRE_DATE"));
emp.setJobId(rs.getString("JOB_ID"));
emp.setSalary(rs.getInt("SALARY"));
emp.setCommissionPct(rs.getDouble("COMMISSION_PCT"));
emp.setManagerId(rs.getInt("MANAGER_ID"));
emp.setDepartmantId(rs.getInt("DEPARTMENT_ID"));
//Add employee to the ObservableList
empList.add(emp);
}
//return empList (ObservableList of Employees)
return empList;

34
}

//*************************************
//UPDATE an employee's email address
//*************************************
public static void updateEmpEmail (String empId, String empEmail) throws SQLException,
ClassNotFoundException {
//Declare a UPDATE statement
String updateStmt =
"BEGIN\n" +
" UPDATE employees\n" +
" SET EMAIL = '" + empEmail + "'\n" +
" WHERE EMPLOYEE_ID = " + empId + ";\n" +
" COMMIT;\n" +
"END;";

//Execute UPDATE operation


try {
DBUtil.dbExecuteUpdate(updateStmt);
} catch (SQLException e) {
System.out.print("Error occurred while UPDATE Operation: " + e);
throw e;
}
}

//*************************************
//DELETE an employee
//*************************************
public static void deleteEmpWithId (String empId) throws SQLException, ClassNotFoundException {
//Declare a DELETE statement
String updateStmt =
"BEGIN\n" +
" DELETE FROM employees\n" +
" WHERE employee_id ="+ empId +";\n" +
" COMMIT;\n" +
"END;";

35
//Execute UPDATE operation
try {
DBUtil.dbExecuteUpdate(updateStmt);
} catch (SQLException e) {
System.out.print("Error occurred while DELETE Operation: " + e);
throw e;
}
}

//*************************************
//INSERT an employee
//*************************************
public static void insertEmp (String name, String lastname, String email) throws SQLException,
ClassNotFoundException {
//Declare a DELETE statement
String updateStmt =
"BEGIN\n" +
"INSERT INTO employees\n" +
"(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, HIRE_DATE, JOB_ID)\n" +
"VALUES\n" +
"(sequence_employee.nextval, '"+name+"', '"+lastname+"','"+email+"', SYSDATE,
'IT_PROG');\n" +
"END;";

//Execute DELETE operation


try {
DBUtil.dbExecuteUpdate(updateStmt);
} catch (SQLException e) {
System.out.print("Error occurred while DELETE Operation: " + e);
throw e;
}
}
}

RootLayout FXML

36
RootLayout contains a border pane and menu items. We need to bind it with
RootLayoutController class.

We have three menus: File, Operations, and Help.

File Menu has Close option to exit the program. Operations menu has “New Menu Item”
option. Help Menu has “About” option to show information about program.
RootLayout View Code:
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"


prefHeight="370.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.controller.RootLayoutController">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#handleExit" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="New Menu Item" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>

37
<MenuItem mnemonicParsing="false" onAction="#handleHelp" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>

EmployeeView FXML
EmployeeView fxml file comprises of text fields, buttons, table view and text area for
employee related operations. We need to bind it with EmployeeController class.

As you see the picture below, we need to declare fx:id values, these values are unique for
each element and we can bind methods with these elements by OnAction tag. Methods must
start with “#” sign.

Employee View Code:


<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"


prefHeight="344.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.controller.EmployeeController">
<children>
<TextField fx:id="empIdText" layoutX="193.0" layoutY="41.0" prefHeight="25.0"
prefWidth="67.0" promptText="Emp ID" />
<Label layoutX="194.0" layoutY="21.0" text="Employee ID" />
<Button fx:id="searchEmpBtn" layoutX="194.0" layoutY="70.0" mnemonicParsing="false"
onAction="#searchEmployee" prefHeight="25.0" prefWidth="56.0" text="Search" />

38
<Button fx:id="deleteEmpBtn" layoutX="332.0" layoutY="70.0" mnemonicParsing="false"
onAction="#deleteEmployee" prefHeight="25.0" prefWidth="56.0" text="Delete" />
<Button fx:id="updateEmpBtn" layoutX="263.0" layoutY="70.0" mnemonicParsing="false"
onAction="#updateEmployeeEmail" prefHeight="25.0" prefWidth="56.0" text="Update" />
<Button fx:id="addEmpBtn" layoutX="82.0" layoutY="114.0" mnemonicParsing="false"
onAction="#insertEmployee" text="Add Employee" />
<TextArea fx:id="resultArea" layoutX="7.0" layoutY="250.0" prefHeight="85.0"
prefWidth="167.0" wrapText="true" />
<Label layoutX="9.0" layoutY="231.0" text="Result Console">
<font>
<Font name="System Bold" size="12.0" />
</font></Label>
<TextField fx:id="newEmailText" layoutX="268.0" layoutY="41.0" prefHeight="25.0"
prefWidth="120.0" promptText="new email" />
<Label layoutX="270.0" layoutY="21.0" text="New Email" />
<VBox layoutX="97.0" layoutY="24.0" spacing="4.0">
<children>
<TextField fx:id="nameText" prefHeight="25.0" prefWidth="79.0" promptText="Name" />
<TextField fx:id="surnameText" prefHeight="25.0" prefWidth="79.0" promptText="Surname"
/>
<TextField fx:id="emailText" prefHeight="25.0" prefWidth="79.0" promptText="email" />
</children>
</VBox>
<VBox layoutX="9.0" layoutY="28.0" prefWidth="67.0" spacing="12.0">
<children>
<Label text="Name" />
<Label text="Surname" />
<Label text="Email" />
</children>
</VBox>
<Separator layoutY="14.0" prefHeight="4.0" prefWidth="600.0" />
<Separator layoutX="180.0" layoutY="14.0" orientation="VERTICAL" prefHeight="333.0"
prefWidth="7.0" />
<TableView fx:id="employeeTable" editable="true" layoutX="193.0" layoutY="102.0"
prefHeight="234.0" prefWidth="393.0" tableMenuButtonVisible="true">
<columns>
<TableColumn fx:id="empIdColumn" prefWidth="57.0" text="Id" />
<TableColumn fx:id="empNameColumn" prefWidth="75.0" text="Name" />

39
<TableColumn fx:id="empLastNameColumn" prefWidth="73.0" text="LastName" />
<TableColumn fx:id="empEmailColumn" prefWidth="79.0" text="Email" />
<TableColumn fx:id="empPhoneNumberColumn" prefWidth="73.0" text="Phone" />
<TableColumn fx:id="empHireDateColumn" prefWidth="93.0" text="Hire Date" />
</columns>
</TableView>
<Button fx:id="searchEmpsBtn" layoutX="396.0" layoutY="70.0" mnemonicParsing="false"
onAction="#searchEmployees" prefHeight="25.0" prefWidth="139.0" text="Search All Employees" />
</children>
</AnchorPane>

RootLayoutController Class
In RootLayoutController class, we handle exit and help methods. Exit method closes program
and help method gives information about program by using Alert class.
RootLayoutController Code:
package sample.controller;

import javafx.event.ActionEvent;

import javafx.scene.control.Alert;

import sample.Main;

public class RootLayoutController {

//Exit the program

public void handleExit(ActionEvent actionEvent) {

System.exit(0);

//Help Menu button behavior

public void handleHelp(ActionEvent actionEvent) {

Alert alert = new Alert (Alert.AlertType.INFORMATION);

alert.setTitle("Program Information");

alert.setHeaderText("This is a sample JAVAFX application for SWTESTACADEMY!");

40
alert.setContentText("You can search, delete, update, insert a new employee with this
program.");

alert.show();

EmployeeController Class
In EmployeeController class, fields and methods have special @FXML annotation. We need
this annotation because fxml file needs to access private fields and private methods. After
these settings, application will automatically fill the variables when the fxml file is loaded.
EmployeeController Class handles below operations:
– searchEmployee() – Searches an employee with given employee id. Then, populate
employee’s information on table view and print the result on text area.
– searchEmployees() – Gets all employees information and populates them on table view.
– initialize() – Handles initialization. When the fxml file is loaded, it will be called
automatically.
– populateEmployee(Employee) – Populates employee on table view.
– setEmpInfoToTextArea(Employee) – Prints employee information on text area.
– populateEmployees(ObservableList<Employee>) – Populates employees.
– updateEmployeeEmail() – Updates employee email by using employee id
– insertEmployee() – Insert a new employee into employee table.
– deleteEmployee() – Deletes an employee with employee’s id.
Extra Explanations:
– Private fields and methods where the fxml file needs to access must be annotated with
@FXML annotation.
– After the fxml file has been loaded, the initialize() method will be called automatically.
– The setCellValueFactory(…) that we set on the table columns are used to determine which
field inside the Employee objects should be used for the particular column. The arrow ->
indicates that we are using a Java 8 feature called Lambdas. (Another option would be to
use a PropertyValueFactory).
– If you use a property which is different than StringProperty, such as IntegerProperty,
DoubleProperty, etc. the setCellValueFactory(…) must have an additional asObject()
method:
empIdColumn.setCellValueFactory(cellData ->
cellData.getValue().employeeIdProperty().asObject());

Note: Always use the javafx imports, NOT awt or swing!


EmployeeController Class Code:
package sample.controller;

41
import javafx.collections.FXCollections;

import javafx.collections.ObservableList;

import javafx.event.ActionEvent;

import javafx.fxml.FXML;

import javafx.scene.control.TableColumn;

import javafx.scene.control.TableView;

import javafx.scene.control.TextArea;

import javafx.scene.control.TextField;

import sample.model.Employee;

import sample.model.EmployeeDAO;

import java.sql.Date;

import java.sql.SQLException;

/**

* Created by ONUR BASKIRT on 23.02.2016.

*/

public class EmployeeController {

@FXML

private TextField empIdText;

@FXML

private TextArea resultArea;

@FXML

private TextField newEmailText;

@FXML

private TextField nameText;

@FXML

private TextField surnameText;

@FXML

42
private TextField emailText;

@FXML

private TableView employeeTable;

@FXML

private TableColumn<Employee, Integer> empIdColumn;

@FXML

private TableColumn<Employee, String> empNameColumn;

@FXML

private TableColumn<Employee, String> empLastNameColumn;

@FXML

private TableColumn<Employee, String> empEmailColumn;

@FXML

private TableColumn<Employee, String> empPhoneNumberColumn;

@FXML

private TableColumn<Employee, Date> empHireDateColumn;

//Search an employee

@FXML

private void searchEmployee (ActionEvent actionEvent) throws ClassNotFoundException,


SQLException {

try {

//Get Employee information

Employee emp = EmployeeDAO.searchEmployee(empIdText.getText());

//Populate Employee on TableView and Display on TextArea

populateAndShowEmployee(emp);

} catch (SQLException e) {

e.printStackTrace();

resultArea.setText("Error occurred while getting employee information from DB.\n" + e);

throw e;

43
//Search all employees

@FXML

private void searchEmployees(ActionEvent actionEvent) throws SQLException,


ClassNotFoundException {

try {

//Get all Employees information

ObservableList<Employee> empData = EmployeeDAO.searchEmployees();

//Populate Employees on TableView

populateEmployees(empData);

} catch (SQLException e){

System.out.println("Error occurred while getting employees information from DB.\n" + e);

throw e;

//Initializing the controller class.

//This method is automatically called after the fxml file has been loaded.

@FXML

private void initialize () {

/*

The setCellValueFactory(...) that we set on the table columns are used to determine

which field inside the Employee objects should be used for the particular column.

The arrow -> indicates that we're using a Java 8 feature called Lambdas.

(Another option would be to use a PropertyValueFactory, but this is not type-safe

We're only using StringProperty values for our table columns in this example.

When you want to use IntegerProperty or DoubleProperty, the setCellValueFactory(...)

must have an additional asObject():

*/

empIdColumn.setCellValueFactory(cellData ->
cellData.getValue().employeeIdProperty().asObject());

44
empNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());

empLastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());

empEmailColumn.setCellValueFactory(cellData -> cellData.getValue().emailProperty());

empPhoneNumberColumn.setCellValueFactory(cellData ->
cellData.getValue().phoneNumberProperty());

empHireDateColumn.setCellValueFactory(cellData -> cellData.getValue().hireDateProperty());

//Populate Employee

@FXML

private void populateEmployee (Employee emp) throws ClassNotFoundException {

//Declare and ObservableList for table view

ObservableList<Employee> empData = FXCollections.observableArrayList();

//Add employee to the ObservableList

empData.add(emp);

//Set items to the employeeTable

employeeTable.setItems(empData);

//Set Employee information to Text Area

@FXML

private void setEmpInfoToTextArea ( Employee emp) {

resultArea.setText("First Name: " + emp.getFirstName() + "\n" +

"Last Name: " + emp.getLastName());

//Populate Employee for TableView and Display Employee on TextArea

@FXML

private void populateAndShowEmployee(Employee emp) throws ClassNotFoundException {

if (emp != null) {

populateEmployee(emp);

45
setEmpInfoToTextArea(emp);

} else {

resultArea.setText("This employee does not exist!\n");

//Populate Employees for TableView

@FXML

private void populateEmployees (ObservableList<Employee> empData) throws


ClassNotFoundException {

//Set items to the employeeTable

employeeTable.setItems(empData);

//Update employee's email with the email which is written on newEmailText field

@FXML

private void updateEmployeeEmail (ActionEvent actionEvent) throws SQLException,


ClassNotFoundException {

try {

EmployeeDAO.updateEmpEmail(empIdText.getText(),newEmailText.getText());

resultArea.setText("Email has been updated for, employee id: " + empIdText.getText() + "\n");

} catch (SQLException e) {

resultArea.setText("Problem occurred while updating email: " + e);

//Insert an employee to the DB

@FXML

private void insertEmployee (ActionEvent actionEvent) throws SQLException,


ClassNotFoundException {

try {

EmployeeDAO.insertEmp(nameText.getText(),surnameText.getText(),emailText.getText());

46
resultArea.setText("Employee inserted! \n");

} catch (SQLException e) {

resultArea.setText("Problem occurred while inserting employee " + e);

throw e;

//Delete an employee with a given employee Id from DB

@FXML

private void deleteEmployee (ActionEvent actionEvent) throws SQLException,


ClassNotFoundException {

try {

EmployeeDAO.deleteEmpWithId(empIdText.getText());

resultArea.setText("Employee deleted! Employee id: " + empIdText.getText() + "\n");

} catch (SQLException e) {

resultArea.setText("Problem occurred while deleting employee " + e);

throw e;

Main Class
At the end of the first JavaFX article, I described details of the main method. In here, I want
to explain it briefly. It starts the primary stage, sets its title, initializes the root layout and then
displays the “employee view”.
Main Class Code:
package sample;

import javafx.application.Application;

import javafx.fxml.FXMLLoader;

import javafx.scene.Scene;

import javafx.scene.layout.AnchorPane;

import javafx.scene.layout.BorderPane;

47
import javafx.stage.Stage;

import java.io.IOException;

//Main class which extends from Application Class

public class Main extends Application {

//This is our PrimaryStage (It contains everything)

private Stage primaryStage;

//This is the BorderPane of RootLayout

private BorderPane rootLayout;

@Override

public void start(Stage primaryStage) {

//1) Declare a primary stage (Everything will be on this stage)

this.primaryStage = primaryStage;

//Optional: Set a title for primary stage

this.primaryStage.setTitle("SW Test Academy - Sample JavaFX App");

//2) Initialize RootLayout

initRootLayout();

//3) Display the EmployeeOperations View

showEmployeeView();

//Initializes the root layout.

public void initRootLayout() {

try {

48
//First, load root layout from RootLayout.fxml

FXMLLoader loader = new FXMLLoader();

loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));

rootLayout = (BorderPane) loader.load();

//Second, show the scene containing the root layout.

Scene scene = new Scene(rootLayout); //We are sending rootLayout to the Scene.

primaryStage.setScene(scene); //Set the scene in primary stage.

/*//Give the controller access to the main.

RootLayoutController controller = loader.getController();

controller.setMain(this);*/

//Third, show the primary stage

primaryStage.show(); //Display the primary stage

} catch (IOException e) {

e.printStackTrace();

//Shows the employee operations view inside the root layout.

public void showEmployeeView() {

try {

//First, load EmployeeView from EmployeeView.fxml

FXMLLoader loader = new FXMLLoader();

loader.setLocation(Main.class.getResource("view/EmployeeView.fxml"));

AnchorPane employeeOperationsView = (AnchorPane) loader.load();

// Set Employee Operations view into the center of root layout.

rootLayout.setCenter(employeeOperationsView);

} catch (IOException e) {

49
e.printStackTrace();

public static void main(String[fusion_builder_container hundred_percent="yes"


overflow="visible"][fusion_builder_row][fusion_builder_column type="1_1"
background_position="left top" background_color="" border_size="" border_color=""
border_style="solid" spacing="yes" background_image="" background_repeat="no-repeat"
padding="" margin_top="0px" margin_bottom="0px" class="" id="" animation_type=""
animation_speed="0.3" animation_direction="left" hide_on_mobile="no" center_content="no"
min_height="none"][] args) {

launch(args);

We finished coding. It is time to run the code.

The result of the program is shown below.

50
Github: https://github.com/swtestacademy/javafxexample

The End

51

You might also like