javajavafxnullpointerexceptionscenebuilderobservablelist

I get a null pointer exception on setCellValueFactory


I'm not sure what is wrong with my code. I tried everything, and it doesn't work yet. The error is below:

Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TableColumn.setCellValueFactory(javafx.util.Callback)" because "this.InvestorIDColumn" is null at application.PagesController.initialize(PagesController.java:93)

The code is as follows

package application;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;

public class PagesController implements Initializable {
    private static String dbUsername = "root"; // database username
    private static String dbPassword = "Ameer12345!"; // database password
    private static String URL = "127.0.0.1"; // server location
    private static String port = "3306"; // port that mysql uses
    private static String dbName = "univ3"; // database on mysql to connect to
    private static Connection con;

    private Stage stage;
    private Scene scene;
    private Parent root;

    @FXML
    private Button myButton;
    @FXML
    private TextField myTextField1;
    @FXML
    private TextField myTextField2;
    @FXML
    private Label myLabel;

    int username;
    @FXML
    TableView<Investor> myInvestorTableView;
    @FXML
    TableColumn<Investor, String> InvestorNameColumn;
    @FXML
    TableColumn<Investor, Integer> InvestorIDColumn;
    @FXML
    TableColumn<Investor, String> InvestorPNumberColumn;
    @FXML
    TableColumn<Investor, String> InvestorEmailColumn;

    public void switchToMainPage(ActionEvent event) throws IOException, ClassNotFoundException, SQLException {

        try {

            username = Integer.parseInt(myTextField1.getText());
            if (username == 112) {

                Parent root = FXMLLoader.load(getClass().getResource("MainPage.fxml"));
                stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
                scene = new Scene(root);
                stage.setScene(scene);
                stage.show();

            } else
                myLabel.setText("wrong username or password ");
        } catch (Exception e) {
            System.out.println("wrong username or password " + e);
        }

    }

    public void switchToLoginPage(ActionEvent event) throws IOException, ClassNotFoundException, SQLException {

        Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
        stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        scene = new Scene(root);
        stage.setScene(scene);
        stage.show();

    }

    @Override
    public void initialize(java.net.URL arg0, ResourceBundle arg1) {
        InvestorIDColumn.setCellValueFactory(new PropertyValueFactory<Investor, Integer>("investor_id"));
        InvestorPNumberColumn.setCellValueFactory(new PropertyValueFactory<Investor, String>("investor_PNumber"));

        InvestorNameColumn.setCellValueFactory(new PropertyValueFactory<Investor, String>("investor_name"));
        InvestorEmailColumn.setCellValueFactory(new PropertyValueFactory<Investor, String>("investor_Email"));
        try {
            myInvestorTableView.setItems(getInvestor());
        } catch (ClassNotFoundException | SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public ObservableList<Investor> getInvestor() throws ClassNotFoundException, SQLException {

        ObservableList<Investor> Investors = FXCollections.observableArrayList();
        DBConn a = new DBConn(URL, port, dbName, dbUsername, dbPassword);
        con = a.connectDB();
        System.out.println("Connection established");
        String SQLtxt = "select * from investor";
        Statement stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery(SQLtxt);
        while (rs.next()) {
            int ID = Integer.parseInt(rs.getString(1));
            String name = rs.getString(3);
            String Pnumber = rs.getString(2);
            ;
            String Email = rs.getString(4);

            Investors.add(new Investor(name, ID, Email, Pnumber));
        }

        rs.close();
        stmt.close();
        con.close();
        System.out.println("Connection closed");

        return Investors;
    }

}

And here is my class:

package application;

import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;

public class Investor {
    private SimpleStringProperty investor_name;
    private SimpleIntegerProperty investor_id;
    private SimpleStringProperty investor_Email;
    private SimpleStringProperty investor_PNumber;

    public Investor(String investor_name, int investor_id, String investor_Email, String investor_PNumber) {
        this.investor_name = new SimpleStringProperty(investor_name);
        this.investor_id = new SimpleIntegerProperty(investor_id);
        this.investor_Email = new SimpleStringProperty(investor_Email);
        this.investor_PNumber = new SimpleStringProperty(investor_PNumber);
    }

    public SimpleStringProperty getInvestor_name() {
        return investor_name;
    }

    public SimpleIntegerProperty getInvestor_id() {
        return investor_id;
    }

    public SimpleStringProperty getInvestor_Email() {
        return investor_Email;
    }
    
    public SimpleStringProperty getInvestor_PNumber() {
        return investor_PNumber;
    }

}

Here is the FXML file:

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.PagesController">
   <children>
      <Button layoutX="531.0" layoutY="361.0" mnemonicParsing="false" onAction="#switchToLoginPage" text="log out" textFill="#bf2626" />
      <MenuBar prefHeight="28.0" prefWidth="576.0" AnchorPane.bottomAnchor="372.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" text="Close" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Edit">
            <items>
              <MenuItem mnemonicParsing="false" text="Delete" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
      <TableView fx:id="myInvestorTableView" layoutY="28.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="172.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="28.0">
        <columns>
          <TableColumn fx:id="InvestorIDColumn" prefWidth="155.0" text="InvestorIDColumn" />
          <TableColumn fx:id="InvestorPNumberColumn" prefWidth="145.0" text="InvestorPNumberColumn" />
            <TableColumn fx:id="InvestorNameColumn" prefWidth="132.0" text="InvestorNameColumn" />
            <TableColumn fx:id="InvestorEmailColumn" prefWidth="158.0" text="InvestorEmailColumn" />
        </columns>
      </TableView>
   </children>
</AnchorPane>

Solution

  • This is the line which throws your error:

    InvestorIDColumn.setCellValueFactory(new PropertyValueFactory<Investor, Integer>("investor_id"));
    

    This data member is declared as

    @FXML
    TableColumn<Investor, Integer> InvestorIDColumn;
    

    but seemingly it does not have a value (yet) when your initialize method is being called. To solve this issue you will need to either initialize this data member (if a null state is invalid), or you can check whether it's null and only call setCellValueFactory if it's not null.

    Maybe the investor id column is empty for some records in your XML.