Login Form Using JavaFX with MySQL Database

In the previous tutorial, we have created registration form using JavaFx with MySQL database. In this tutorial, we will learn how to create a Login Form using JavaFX with database connectivity.
Check out Registration Form Using JavaFX with MySQL Database.

Note that in this tutorial, we are using FXML, an XML based language provided by JavaFX, to create the user interface for our Desktop application.
In the previous tutorial, we have registered a user with registration form and in this tutorial, we will authenticate login user with a registered user in the registration table. 
This JavaFX application will have a login form where the user enters login details and then submit the form. When the user submits the login form, the login form data will validate with MySQL database via JDBC API.

What will you learn?

In this tutorial, you’ll learn -
  1. How to create the layout of a JavaFX application window using FXML.
  2. How to add UI controls like Text Field, Password Field, and Button.
  3. How to validate UI controls like Text Field, Password Field.
  4. How to connect JavaFX application with MySQL database via JDBC API.

Tools and Technologies used

  • JDK 1.8
  • MySQL Connector Java - 8.0.13
  • JDBC - 4.2
  • Eclipse IDE
  • JavaFX

Development steps

  1. Create a Simple Maven Project
  2. Add Dependencies
  3. Project Structure
  4. Database Setup
  5. Create the Main Application Class
  6. Create the Layout for Our Application using FXML
  7. Create a Login Controller to handle form data
  8. Create JDBCDao for Database operations
  9. Run application
  10. Output

1. Create a Simple Maven Project

Let's create a simple maven project and name this project as "javafx-login-form-jdbc-tutorial". Refer below step by step tutorial to create a simple maven project.

2. Add Dependencies

Let's add MySQL driver maven dependency to above-created maven project:
<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.javaguides.javafx</groupId>
    <artifactId>javafx-login-form-jdbc-tutorial</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>javafx-login-form-jdbc-tutorial</name>
    <description>javafx-login-form-jdbc-tutorial</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <mainClass>com.javaguides.javafx.registration.MainApp</mainClass>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3. Project Structure

Refer below screenshot to create a project or packaging structure for this application -

4. Database Setup

In the registration form using JavaFx with MySQL database tutorial, we have created a database set up with a registration table. We have registered a user with registration form and in this tutorial, we will authenticate login user with a registered user in the registration table.

5. Create the Main Application Class

Let’s first write the MainApp application class. As usual, For creating a JavaFX application, we’ll need to extend our MainApp class from javafx.application.Application and override its start() method.
package com.javaguides.javafx.login;

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


public class MainApp extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        System.out.println(getClass());
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/login_form.fxml"));
        stage.setTitle("User Login");
        stage.setScene(new Scene(root, 800, 500));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}
We first load the FXML document using FXMLLoader. We wil create login_form.fxml file in next step.

6. Create the Layout for Our Application using FXML

We’ll use JavaFX GridPane layout for designing the login form. It enables us to create a flexible grid of rows and columns in which to layout UI-controls.
<?import javafx.scene.layout.GridPane?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.Button?>
<GridPane fx:controller="com.javaguides.javafx.login.LoginController"
    xmlns:fx="http://javafx.com/fxml" alignment="center"
          hgap="10" vgap="10">
    <padding>
        <Insets top="40" right="40" bottom="40" left="40"/>
    </padding>
    <columnConstraints>
        <ColumnConstraints minWidth="100" prefWidth="100"
                           maxWidth="Infinity" halignment="RIGHT"></ColumnConstraints>
        <ColumnConstraints minWidth="200" prefWidth="200"
                           maxWidth="Infinity" hgrow="ALWAYS"></ColumnConstraints>
    </columnConstraints>
    <!-- Add Header Label -->
    <Label text="Login Form (FXML)" GridPane.columnIndex="0" 
           GridPane.rowIndex="0" GridPane.columnSpan="2" 
           GridPane.rowSpan="1" GridPane.halignment="CENTER" >
        <font>
            <Font name="Arial" size="24" ></Font>
        </font>
        <GridPane.margin>
            <Insets top="20" right="0" bottom="20" left="0"></Insets>
        </GridPane.margin>
    </Label>
    <!-- Add Email Label -->
    <Label text="Email ID : " GridPane.columnIndex="0" 
           GridPane.rowIndex="2" ></Label>
    <!-- Add Email Text Field -->
    <TextField fx:id="emailIdField" prefHeight="40" 
               GridPane.columnIndex="1" GridPane.rowIndex="2"/>
    <!-- Add Password Label -->
    <Label text="Password : " GridPane.columnIndex="0" 
           GridPane.rowIndex="3" ></Label>
    <!-- Add Password Field -->
    <PasswordField fx:id="passwordField" prefHeight="40" 
                   GridPane.columnIndex="1" GridPane.rowIndex="3"/>
    <!-- Add Submit Button -->
    <Button fx:id="submitButton" text="Submit"
            prefWidth="100" prefHeight="40" defaultButton="true"
            GridPane.columnIndex="0" GridPane.rowIndex="4"
            GridPane.columnSpan="2" GridPane.rowSpan="1"
            GridPane.halignment="CENTER"
            onAction="#login">
        <GridPane.margin>
            <Insets top="20" right="0" bottom="20" left="0"></Insets>
        </GridPane.margin>
    </Button>
</GridPane>
The above FXML document is self-explanatory.
In the above FXML document, We create a GridPane layout which is center aligned and has a horizontal and vertical gap of 10.
We also specify padding of 40px on each side. The layout also defines the controller that will be used to handle any mouse or keyboard events using fx:controller property.
GridPane.columnIndex and GridPane.rowIndex properties allow us to place ui controls in a particular cell.
The Submit button has an onAction property which calls a method named submitButton. This method has to be defined in the FXML controller and that’s we will create in the next step.

7. Create a Login Controller to Handle Form Data

Let's create a LoginController.java class and add the following content to it:
package com.javaguides.javafx.login;

import java.sql.SQLException;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Window;

public class LoginController {

    @FXML
    private TextField emailIdField;

    @FXML
    private PasswordField passwordField;

    @FXML
    private Button submitButton;

    @FXML
    public void login(ActionEvent event) throws SQLException {

        Window owner = submitButton.getScene().getWindow();

        System.out.println(emailIdField.getText());
        System.out.println(passwordField.getText());

        if (emailIdField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, owner, "Form Error!",
                "Please enter your email id");
            return;
        }
        if (passwordField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, owner, "Form Error!",
                "Please enter a password");
            return;
        }

        String emailId = emailIdField.getText();
        String password = passwordField.getText();

        JdbcDao jdbcDao = new JdbcDao();
        boolean flag = jdbcDao.validate(emailId, password);

        if (!flag) {
            infoBox("Please enter correct Email and Password", null, "Failed");
        } else {
            infoBox("Login Successful!", null, "Failed");
        }
    }

    public static void infoBox(String infoMessage, String headerText, String title) {
        Alert alert = new Alert(AlertType.CONFIRMATION);
        alert.setContentText(infoMessage);
        alert.setTitle(title);
        alert.setHeaderText(headerText);
        alert.showAndWait();
    }

    private static void showAlert(Alert.AlertType alertType, Window owner, String title, String message) {
        Alert alert = new Alert(alertType);
        alert.setTitle(title);
        alert.setHeaderText(null);
        alert.setContentText(message);
        alert.initOwner(owner);
        alert.show();
    }
}
Note that the FXMLLoader will automatically inject values defined in the FXML document into corresponding references in the controller class.
So, the emailIdField, passwordField and submitButton references specified in the above controller will automatically be injected by the objects created from the FXML document.
The @FXML annotation is mandatory for private member fields of the controller class, otherwise, field injection won’t work. However, it can be omitted for public fields.
We validate form fields and store to a database using JdbcDao class.

8. Create JDBCDao for Database operations

Here are steps to connect to the MySQL database:
  1. Establishing a connection
  2. Create a statement
  3. Execute the query
  4. Using try-with-resources Statements to Automatically Close JDBC Resources
From JDBC 4.0, we don't need to include 'Class.forName()' in our code, to load JDBC driver. When the method 'getConnection' is called, the 'DriverManager' will automatically load the suitable driver among the JDBC drivers that were loaded at initialization and those loaded explicitly using the same class loader as the current application.
Connection conn = DriverManager.getConnection(Urldatabase,Username,Password);
Any JDBC 4.0 drivers that are found in your classpath are automatically loaded. (However, you must manually load any drivers prior to JDBC 4.0 with the method Class.forName.)
Here is complete code to validate user login form-data with MySQL database:
 package com.javaguides.javafx.login;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JdbcDao {

    // Replace below database url, username and password with your actual database credentials
    private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/javafx_registration?useSSL=false";
    private static final String DATABASE_USERNAME = "root";
    private static final String DATABASE_PASSWORD = "root";
    private static final String SELECT_QUERY = "SELECT * FROM registration WHERE email_id = ? and password = ?";

    public boolean validate(String emailId, String password) throws SQLException {

        // Step 1: Establishing a Connection and 
        // try-with-resource statement will auto close the connection.
        try (Connection connection = DriverManager
            .getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);

            // Step 2:Create a statement using connection object
            PreparedStatement preparedStatement = connection.prepareStatement(SELECT_QUERY)) {
            preparedStatement.setString(1, emailId);
            preparedStatement.setString(2, password);

            System.out.println(preparedStatement);

            ResultSet resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                return true;
            }


        } catch (SQLException e) {
            // print SQL exception information
            printSQLException(e);
        }
        return false;
    }

    public static void printSQLException(SQLException ex) {
        for (Throwable e: ex) {
            if (e instanceof SQLException) {
                e.printStackTrace(System.err);
                System.err.println("SQLState: " + ((SQLException) e).getSQLState());
                System.err.println("Error Code: " + ((SQLException) e).getErrorCode());
                System.err.println("Message: " + e.getMessage());
                Throwable t = ex.getCause();
                while (t != null) {
                    System.out.println("Cause: " + t);
                    t = t.getCause();
                }
            }
        }
    }
}

9. Run application

In order to run this JavaFX application, open MainApp.java file which contains main() method so write click -> Run As -> Java Application.

10. Output

Following are some screenshots of the application we just built.

Login Form Validation:


Login Form Valid Data:

Login Form Success:


Get source code of this tutorial on my GitHub Repository.

Comments