How to make autmatic popup notification in scene2 when record is inserted into the database from scene1 using javafx

61 Views Asked by At

I am developing booking system. It will have 2 main users. When user1 request booking for a vehicle, user2 will receive a popup notification stating that user1 is requesting a booking for a vehicle.

When user1 sends a vehicle booking request, the request data should be inserted in the database. In user2 controller, user2 should check/read the database and if there is new request received then there should be an automatic popup notification.

Below is my code for user2 controller to read the database and prompt a popup notification when new record exist.

I am using the TrayNotification. But it didn't popup when the app is currently open and running. However, it only popup when user login to the user2 account, after that when new bookings were made it never popup.

User2 Code:

//-------------------------- get Notifications --------------------------//
    public void getNotification() throws ClassNotFoundException, SQLException{
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost/vbms_db";
        conn =(Connection) DriverManager.getConnection(url,"root","");
        System.out.println("Connected");
        try { 
            getDepartment= lbl_holdUserDepartment.getText();
            pst = conn.prepareStatement("SELECT * FROM bookings WHERE driver_department='"+getDepartment+"' AND vehicle_AvailStatus = 'Pending...'");
            rs = pst.executeQuery();
            if(rs.next()==true){
                NotificationType nt = NotificationType.WARNING;
                TrayNotification tray = new TrayNotification();
                tray.setTitle("Notification");
                tray.setMessage("Vehicle Booking Requested.");
                tray.showAndDismiss(Duration.millis(3000));
                tray.setNotificationType(nt);         
            }
        } catch (SQLException exception) {
            System.out.println(exception);
        }
    }

Really need help.

1

There are 1 best solutions below

1
SedJ601 On

I could not get TrayNotification to work with the latest version of JavaFX. I used ControlsFX Notification. The ideas should be very similar.

Use ScheduledService to periodically check new db notifications. If ScheduledService finds new notifications, stop ScheduledService from looking for new notifications. Display the current notifications using Timeline. Restart the ScheduledService once the Timeline finishes displaying the current notifications.

Main

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Duration;
import org.controlsfx.control.Notifications;

public class App extends Application {
    
    static List<MyNotification> myNotifications = new ArrayList();
    static FakeDatabaseHandler fakeDatabaseHandler = new FakeDatabaseHandler();
    
    @Override
    public void start(Stage stage) {
        
        Button btnGenerateNotification = new Button("Generate!");
        btnGenerateNotification.setOnAction(actionEvent ->{            
             fakeDatabaseHandler.addFakeNotificationsToDb();
        });

        Label lblUpdateMessage = new Label("Update Message: ");
        
        ScheduledService<List<MyNotification>> checkForScheduledService = new CheckForNotificationsScheduledService();
        checkForScheduledService.setPeriod(Duration.seconds(5));
        checkForScheduledService.messageProperty().addListener((ov, oldValue, newValue) -> {
            if(newValue != null)
            {
                lblUpdateMessage.setText("Update Message: " + newValue);
            }
        });
        
        checkForScheduledService.valueProperty().addListener((ov, oldValue, newValue) -> {
            if(newValue != null && !newValue.isEmpty())
            {
                myNotifications.clear();
                myNotifications.addAll(newValue);
                checkForScheduledService.cancel();
                
                AtomicInteger index = new AtomicInteger(0);
                checkForScheduledService.cancel();
                Timeline threeSecondsWonder = new Timeline(
                    new KeyFrame(Duration.seconds(3),  event -> {    
                        MyNotification myNotification = myNotifications.get(index.getAndIncrement());
                        Notifications.create().title(myNotification.getDepartment() + " - " + myNotification.getTitle()).text(myNotification.getMessage()).hideAfter(Duration.seconds(3)).showWarning();
                    })
                );
                threeSecondsWonder.setCycleCount(myNotifications.size());
                threeSecondsWonder.play();
                threeSecondsWonder.setOnFinished((t) -> {
                    checkForScheduledService.restart();
                });
            }
        });
        checkForScheduledService.start();
        
        StackPane root = new StackPane(new VBox(btnGenerateNotification, lblUpdateMessage));

        stage.setScene(new Scene(root, 500, 500));
        stage.setTitle("Facilities");
        stage.show();        
    }

    public static void main(String[] args) {
        launch(args);
    }
    
    private static class CheckForNotificationsScheduledService extends ScheduledService<List<MyNotification>> {

    @Override
    protected Task<List<MyNotification>> createTask() {
        return new Task<List<MyNotification>>() {
            @Override
            protected List<MyNotification> call() throws Exception {
                List<MyNotification> fakeNotificationList = fakeDatabaseHandler.getFakeNotificationsFromDB();
                System.out.println("Checking for notifications. Notifications Found: " + fakeNotificationList.size());
                updateMessage("Checking for notifications. Notifications Found: " + fakeNotificationList.size());
                updateValue(fakeNotificationList);                
                
                return fakeNotificationList; 
            }
        };
    }
  }
}

MyNotification

/**
 *
 * @author Sed
 */
public class MyNotification {
    private String department;
    private String title;
    private String message;

    public MyNotification(String department, String title, String message) {
        this.department = department;
        this.title = title;
        this.message = message;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("MyNotification{");
        sb.append("department=").append(department);
        sb.append(", title=").append(title);
        sb.append(", message=").append(message);
        sb.append('}');
        return sb.toString();
    }
}

FakeDatabaseHandler

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 *
 * @author Sed
 */
public class FakeDatabaseHandler {
    private final List<MyNotification> fakeDBData = new ArrayList();
    
    //private Connection connection;
    
    public FakeDatabaseHandler() {
        //Estiblish the connection here
        /*
         try {
            connection = DriverManager.getConnection("jdbc:sqlite:vbms_db.db");
            System.out.println("Connected to SQLite Db: vbms_db.db");
        }
        catch (SQLException ex) {
            System.out.println(ex.toString());
        }
        */
    }
    
    public void addFakeNotificationsToDb(){
        List<String> departmentList = Arrays.asList("A", "B", "C", "D");
        //Use a PreparedStatement here! I am not gonig to demo that!      
        
        //Generating Fake DB data!
        
        
        for(int i = 0; i < ThreadLocalRandom.current().nextInt(1, 6); i++)
        {
            int notificationID = ThreadLocalRandom.current().nextInt( 1000000);
            fakeDBData.add(new MyNotification("Department: " + departmentList.get(ThreadLocalRandom.current().nextInt(4)), "Title " + notificationID, "Message: " + notificationID));
        }
    }
    
    public List<MyNotification> getFakeNotificationsFromDB(){
        List<MyNotification> returnList = new ArrayList(fakeDBData);
        fakeDBData.clear();
        
        return returnList;
    }
}

Module-Info

module sed.home.simpletestjavafx {
    requires javafx.controls;
    requires org.controlsfx.controls;
    
    exports sed.home.simpletestjavafx;
}

Output

enter image description here