NullPointerException in JavaFX initialize method

13,057

Your Error

Don't modify anything which is connected to the active scene graph from any other thread than the JavaFX Application Thread.

Background Information

See the JavaFX Concurrency Tutorial and also Usage of JavaFX Platform.runLater and access to UI from a different thread for an explanation of this rule.

As your data list is an ObservableList backing a TableView displayed in the active scene graph, as you modify the ObservableList, it fires change events to the TableView modifying it from your user thread rather than the JavaFX Application Thread - this causes race conditions and inconsistent program failures.

How to Fix it

To fix your issue, wrap the call to update the data item inside Platform.runLater:

Platform.runLater(new Runnable() {
  @Override public void run() {
    data.add(item);
  }
});

The contents of the run method submitted to Platform.runLater are executed on the JavaFX Application Thread.

Share:
13,057
user2150038
Author by

user2150038

Updated on June 14, 2022

Comments

  • user2150038
    user2150038 almost 2 years

    I have controller and there I trying get INBOX folder from e-mail server. With downloading everything is ok. I can put this data(email subject,from,date) into TableView but... only when I am waiting for thread responsible for set this data in TableView. Code:

    // The table and columns
    @FXML
    TableView<MainModel.Item> itemTbl;
    @FXML
    TableColumn itemNameCol;
    @FXML
    TableColumn itemQtyCol;
    @FXML
    TableColumn itemTitleCol;
    // The table's data
    static ObservableList<MainModel.Item> data;
    
    public void dataSet(){
        // Set up the table data
        itemNameCol.setCellValueFactory(
            new PropertyValueFactory<MainModel.Item,String>("name")
        );
        itemQtyCol.setCellValueFactory(
            new PropertyValueFactory<MainModel.Item,String>("qty")
        );
        itemTitleCol.setCellValueFactory(
            new PropertyValueFactory<MainModel.Item,String>("title")
        );
    
        data = FXCollections.observableArrayList();
        itemTbl.setItems(data);
    }
    
    public void setEnemyEvent() {
        itemTbl.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if (event.getClickCount() == 2) {
                    if(itemTbl.getSelectionModel().getSelectedItem()!=null){
                        System.out.println(itemTbl.getSelectionModel().getSelectedItem().name);
                    }
                }
            }
        });
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) { 
        setEnemyEvent();
        dataSet();
        Thread t = new Thread(new MessageLoop());
        //HERE:
        t.start();
        //of course normally here is try and catch
        t.join();
    }
    
    //staric nested class "for loop"
    private static class MessageLoop implements Runnable {
        public void run() {
            try {
                EmailConnetion con = new EmailConnetion();
                MainModel MainModel = new MainModel();
                for(int i=0;i<con.message.length;i++){
                    try{
                        MainModel.Item item = MainModel.new Item();
                        item.name.setValue(i+""+con.message[i].getFrom()[0].toString());
                        item.qty.setValue(con.message[i].getSentDate().toString());
                        item.title.setValue(con.message[i].getSubject().toString());
                        //Here is a problem.
                        data.add(item);//This indicate my IDE  
                        //*****************
                    } catch(AddressException e) {
                        System.out.println("Error : " + "AddressException:"+i);
                    }
                }
            } catch (NoSuchProviderException ex) {
                Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
            } catch (MessagingException ex) {
                Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    

    When i remove t.join() it will throw this NullPointerException.

    Exception in thread "Thread-3" java.lang.NullPointerException
        at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:291)
        at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
        at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:74)
        at javafx.scene.control.TableView$TableViewArrayListSelectionModel$3.onChanged(TableView.java:1725)
        at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:134)
        at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
        at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
        at com.sun.javafx.collections.ObservableListWrapper.clear(ObservableListWrapper.java:184)
        at javafx.scene.control.TableView$TableViewArrayListSelectionModel.quietClearSelection(TableView.java:2154)
        at javafx.scene.control.TableView$TableViewArrayListSelectionModel.updateSelection(TableView.java:1902)
        at javafx.scene.control.TableView$TableViewArrayListSelectionModel.access$2600(TableView.java:1681)
        at javafx.scene.control.TableView$TableViewArrayListSelectionModel$8.onChanged(TableView.java:1802)
        at com.sun.javafx.scene.control.WeakListChangeListener.onChanged(WeakListChangeListener.java:71)
        at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:291)
        at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
        at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
        at com.sun.javafx.collections.ObservableListWrapper.add(ObservableListWrapper.java:154)
        at com.sun.javafx.collections.ObservableListWrapper.add(ObservableListWrapper.java:144)
        at javasplitpane.SimpleController$MessageLoop.run(SimpleController.java:95)
        at java.lang.Thread.run(Thread.java:722)
    

    This appear in different position, in fourteen email, thirty email. You have some ideas ?

    p.s I can't wait for this downloading because it takes 20 sec. with 50 emails - I have to do it during initialize.