mysqljavafxjavafx-webenginejavafx-webview

Javafx webhistory entries insert duplicate browsing histories when I use the textfield assigned for addressbar


Hi I am working on my web browser javafx project where I am storing my browsing history into mysql. There is a bug where everytime I use the addressbar to browse new websites, the history entries insert duplicates.

This is the code that collects and sends data to MySQL.

private void collectData() {
    WebHistory history = web.getEngine().getHistory();
    ObservableList<WebHistory.Entry> entries = history.getEntries();
    DatabaseConnection connectNow=new DatabaseConnection(); 
    
    try {
        connectDB = connectNow.getConnection();
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
    
    String insertTrackData="INSERT INTO `trackdata` (username, sitename, date) VALUES ('"+Session.getSessionUser()+"','"+entries.get(history.getCurrentIndex()).getUrl()+"','"+entries.get(history.getCurrentIndex()).getLastVisitedDate()+"');";
    System.out.println(insertTrackData);
        
    try {
        Statement statement = connectDB.createStatement();
        statement.executeUpdate(insertTrackData);
        
    } catch (Exception e) {
        e.printStackTrace();
        e.getCause();
    }
}

I am wondering if this code is the culprit below

@FXML
private void load(ActionEvent event) {
    web.prefHeightProperty().bind(mainWindow.heightProperty());
    web.prefWidthProperty().bind(mainWindow.widthProperty());
    
    if(!addressBar.getText().contains("https://")) {
        web.getEngine().load("https://" + addressBar.getText());
    } else if(addressBar.getText().contains("https://")) {
        web.getEngine().load(addressBar.getText());
    }
    WebEngine webEngine = web.getEngine();
    
    webEngine.getLoadWorker().stateProperty().addListener((obs, oldValue, newValue) -> {
        if (newValue == Worker.State.SUCCEEDED) {
            WebHistory history = web.getEngine().getHistory();
            ObservableList<WebHistory.Entry> entries = history.getEntries();
            addressBar.setText(entries.get(history.getCurrentIndex()).getUrl());
            
            Stage stage = (Stage) addressBar.getScene().getWindow();
            stage.setTitle(entries.get(history.getCurrentIndex()).getTitle());
            collectData();
        } else if (newValue == Worker.State.FAILED) {
            System.out.println("Loading failed");
        }
     });
}

The console shows this:

INSERT INTO trackdata (username, sitename, date) VALUES ('m','https://www.google.com.hk/','Fri Nov 19 10:48:34 CST 2021');

INSERT INTO trackdata (username, sitename, date) VALUES ('m','https://edition.cnn.com/','Fri Nov 19 10:48:55 CST 2021');

INSERT INTO trackdata (username, sitename, date) VALUES ('m','https://edition.cnn.com/','Fri Nov 19 10:48:55 CST 2021');

INSERT INTO trackdata (username, sitename, date) VALUES ('m','https://www.imdb.com/','Fri Nov 19 10:49:17 CST 2021');

INSERT INTO trackdata (username, sitename, date) VALUES ('m','https://www.imdb.com/','Fri Nov 19 10:49:17 CST 2021');

INSERT INTO trackdata (username, sitename, date) VALUES ('m','https://www.imdb.com/','Fri Nov 19 10:49:17 CST 2021');

Note that the value only duplicates when I enter a new address in the addressbar.


Solution

  • Every time you call method load you add another listener to the same state property of the same WebEngine and each of those listeners executes. That's why your console shows the first URL once, the second URL twice, the third URL three times and so on.

    You only need to add the listener once.