0

I followed this post to accomblish Date formatting, but got java.lang.NullPointerException

Controller Class:

Here is my code: The FXML File:

    <AnchorPane id="AnchorPane" prefHeight="864.0" prefWidth="1090.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.60" fx:controller="idehmis.controller.PersonController">
    <children>
        <BorderPane layoutX="418.0" layoutY="159.0" prefHeight="705.0" prefWidth="1090.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="159.0">
            <center>
                <TableView fx:id="personTable" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
                    <columns>
                        <TableColumn prefWidth="75.0" text="C1" />
                        <TableColumn prefWidth="75.0" text="C2" />
                    </columns>
                </TableView>
            </center>
        </BorderPane>
        <JFXTextField fx:id="Pmrn" layoutX="49.0" layoutY="43.0" maxWidth="117.0" minWidth="106.0" nodeOrientation="LEFT_TO_RIGHT" prefColumnCount="8" prefHeight="31.0" prefWidth="117.0" promptText="MRN" unFocusColor="#0f098a">
        </JFXTextField>
        <JFXTextField fx:id="Plastname" layoutX="47.0" layoutY="88.0" maxWidth="121.0" minWidth="106.0" nodeOrientation="LEFT_TO_RIGHT" prefColumnCount="8" prefHeight="31.0" prefWidth="117.0" promptText="Last Name" unFocusColor="#190879">
        </JFXTextField>
        <JFXDatePicker fx:id="Pdateofbirth" layoutX="210.0" layoutY="43.0" prefHeight="31.0" prefWidth="201.0" promptText="Date Of Birth" />
        <Button fx:id="getAllData" layoutX="573.0" layoutY="30.0" mnemonicParsing="false" onAction="#SubmitButton" text="Retrieve data" />
    </children>
</AnchorPane>

Here is the Person Class:

public class Person {

    public final StringProperty mrn;
    public final StringProperty lastname;
    //public final StringProperty dateofbirth;
    public ObjectProperty<LocalDate> dateofbirth = new SimpleObjectProperty<>();

    public Person() {
        this.mrn = new SimpleStringProperty();
        this.lastname = new SimpleStringProperty();
        //this.dateofbirth = new SimpleStringProperty();
        this.dateofbirth = new SimpleObjectProperty<>();
    }

    public String getMRN() {
        return mrn.get();
    }

    public void setMRN(String mrn) {
        this.mrn.set(mrn);
    }

    public StringProperty mrnProperty() {
        return mrn;
    }

    public String getLarstName() {
        return lastname.get();
    }

    public void setLastName(String lastName) {
        this.lastname.set(lastName);
    }

    public StringProperty lastNameProperty() {
        return lastname;
    }

    public Object getDateOfBirth() {
        return dateofbirth.get();
    }

    public void setDateOfBirth(LocalDate dateofbirth) {
        this.dateofbirth.set(dateofbirth);
    }

    public ObjectProperty<LocalDate> dateOfBirthProperty() {
        return dateofbirth;
    }
}

And Here is the Controller:

    public class PersonController implements Initializable {

    @FXML
    private TableView<Person> personTable;
    @FXML
    private JFXTextField Pmrn;
    @FXML
    private JFXTextField Plastname;
    @FXML
    private JFXDatePicker Pdateofbirth;
    @FXML
    private ObservableList<Person> data;
    @FXML
    private Button getAllData;
    @FXML
    TableColumn<Person, String> MRN;
    @FXML
    TableColumn<Person, String> LASTNAME;
    @FXML
    TableColumn<Person, LocalDate> DATEOFBIRTH;
    SimpleDateFormat sdf = new SimpleDateFormat("dd,MMM,yyyy", Locale.getDefault());

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        DATEOFBIRTH.setCellValueFactory(new PropertyValueFactory<>("dateOfBirth"));
        DATEOFBIRTH.setCellFactory(new PersonController.ColumnFormatter<>(DateTimeFormatter.ofPattern("MM/dd/yyyy")));
    }
    @FXML
    void SubmitButton(ActionEvent event) {
        if (event.getSource() == getAllData) {
            try {
                populatetData();
            } catch (Exception ex) {
                out.println(ex);
            }
        }
    }
    private class ColumnFormatter<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {

        private final DateTimeFormatter format;

        public ColumnFormatter(DateTimeFormatter format) {
            super();
            this.format = format;
        }

        @Override
        public TableCell<S, T> call(TableColumn<S, T> arg0) {
            return new TableCell<S, T>() {
                @Override
                protected void updateItem(T item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty) {
                        setGraphic(null);
                    } else {
                        LocalDate ld = (LocalDate) item;
                        String val = ld.format(format);
                        setGraphic(new Label(val));
                    }
                }
            };
        }
    }

    @SuppressWarnings("Convert2Lambda")
    public void populatetData() throws Exception {
        Connection conn = null;
        Person pt = new Person();
        conn = DBConnection.getConnection();
        String SQL;
        Person p = new Person();
        try {
            conn = DBConnection.getConnection();
            data = FXCollections.observableArrayList();
            SQL = "SELECT MRN, LASTNAME, DATEOFBIRTH FROM " + "HIVP.PATIENT";
            out.println(SQL);
            ResultSet rs = conn.createStatement().executeQuery(SQL);
            if (rs != null) {
                while (rs.next()) {
                    p.setMRN(rs.getString(1));
                    p.setLastName(rs.getString(2));
                    Date x = rs.getDate(3);
                    if (x != null) {
                        p.setDateOfBirth(rs.getDate(3).toLocalDate());
                    } else {
                        p.setDateOfBirth(LocalDate.MIN);
                    }
                    data.addAll(p);
                }
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        personTable.setItems(data);
                    }
                });
            }
        } catch (Exception e) {
            out.println("ERROR GETTING DATA: " + e);
        } finally {
            if (conn != null) {
                DBConnection.closeConnection((OracleConnection) conn);
            }
        }
    }
}


Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: 
file:/C:/Users/abayazids15/Documents/NetBeansProjects/IDEHMIS/dist/run1719879236/IDEHMIS.jar!/idehmis/view/Person.fxml
file:/C:/Users/abayazids15/Documents/NetBeansProjects/IDEHMIS/dist/run1719879236/IDEHMIS.jar!/idehmis/view/mainApplication.fxml:66

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.access$2700(FXMLLoader.java:103)
    at javafx.fxml.FXMLLoader$IncludeElement.constructValue(FXMLLoader.java:1143)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:746)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
    at idehmis.IDEHMIS.start(IDEHMIS.java:21)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    ... 1 more
Caused by: java.lang.NullPointerException
    at idehmis.controller.PersonController.initialize(PersonController.java:58)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    ... 23 more
Exception running application idehmis.IDEHMIS
Java Result: 1

What did I do wrong to get NullPointException. Please Help.Thanks

Community
  • 1
  • 1
FullOfLife
  • 3
  • 2
  • 7
  • My apology the Title is messed up: Should read: Formatting Date Column in javaFX TableView for Data retrieved from Oracle DB – FullOfLife Mar 23 '17 at 16:03
  • It looks like the problem is more on the link between your controller and your fxml file... maybe you misspelled some of the @FXML elements? – negste Mar 24 '17 at 11:10
  • Thank you negste for your reply. I checked my FXML file everything is consistence. When I comment out these lines inside the try ..catch block in the initialize method, the application startup fine but the formatting doesn't work, beside I get one line of error java.lang.NullPointerException. That long error code get produced when I put the code out on try catch.If needed I can put the whole code includinf the DAO file too. – FullOfLife Mar 24 '17 at 11:54
  • see my answer, hope it helps – negste Mar 27 '17 at 08:21
  • I created a Person class, with controller and a simple FXML file to be able to upload all codes. Still getting the same error at the first line inside the initialize method when trying to setValueFactory `MRN.setCellValueFactory(new PropertyValueFactory<>("mrn"));` – FullOfLife Apr 03 '17 at 12:40

1 Answers1

0

You simply forgot to put IDs in your columns... It has to be like this:

<TableColumn fx:id="MRN" prefWidth="75.0" text="C1" />
<TableColumn fx:id="LASTNAME" prefWidth="75.0" text="C2" />

Without them your MRN field in the "initialize" method remains "null" because the FXMLLoader does not find a matching (by ID) field in the fxml file. In my opinion, while having two fields with names that differ only by case (in your code, for example, the TextField "mrn" and the TableColumn "MRN") actually works, it is quite confusing.

Moreover there are problems with your data model and with your method populateData:

  • First of all your TableView should be of type Person, not List: Person is the type of data your Table will hold. Consequently the TableColumns should be declared as TableColumn
  • Second, you have to decide if you want to use FXML or use Java code. You have the columns in the table already (via FXML), but in your populateData method you clear them and try to add them again. If you know the columns beforehand then just use FXML and cut this part of your populateData method away
  • Third when you read the results you get from database, you should create a Person object for each row and then add that object to your data list. Something like this:

            while (rs.next()) {                   
                Person p = new Person();
                p.setMRN(rs.getString(1));
                p.setLastName(rs.getString(2));
                Date x = rs.getDate(3);
                if (x != null) {
                    p.setDateOfBirth(rs.getDate(3).toLocalDate());
                } else {
                    p.setDateOfBirth(LocalDate.MIN);
                }
                data.add(p);
            } 
    

Try following your code with a debugger, it will help you understand.

As for the date formatting I suggest using a DateTimeFormatter:

DATEOFBIRTH.setCellValueFactory(new PropertyValueFactory<>("dateOfBirth"));
DATEOFBIRTH.setCellFactory(new PersonController.ColumnFormatter<>(DateTimeFormatter.ofPattern("MM/dd/yyyy")));

and modify ColumnFormatter this way:

private class ColumnFormatter<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {

    private final DateTimeFormatter format;

    public ColumnFormatter(DateTimeFormatter format) {
        super();
        this.format = format;
    }

    @Override
    public TableCell<S, T> call(TableColumn<S, T> arg0) {
        return new TableCell<S, T>() {
            @Override
            protected void updateItem(T item, boolean empty) {
                super.updateItem(item, empty);
                if (item == null || empty) {
                    setGraphic(null);
                } else {
                    LocalDate ld = (LocalDate) item;
                    String val = ld.format(format);
                    setGraphic(new Label(val));
                }
            }
        };
    }
}
negste
  • 323
  • 1
  • 10
  • Thank you negste. That made the error go away, but still I'm not getting the date formatted. Do you have any idea how to fix it? Thank you. – FullOfLife Apr 03 '17 at 14:20
  • I didn't get this part of your answer **If you know the columns beforehand then just use FXML and cut this part of your populateData method away** The reason I did Method that way was I'm populating data dynamically, I have 15 table user select the table and the selection passed to the query. The Person, and PersonControoler classes are experiment. I changed the code according to your recommendation. I get only one date is selected and populated repeatedly by the number of the record in the database table. The MRN and lastName are not populated at all. Please check my change in the code. Thx – FullOfLife Apr 04 '17 at 20:09
  • MRN and lastName now are not populated because you removed their "setCellValueFactory" in the "init" method of the controller. As for the repeated date, you should not do "data.addAll(p)" but "data.add(p)" (in the "populateData" method, while you iterate over the resultset). – negste Apr 05 '17 at 08:11
  • I tried that too, it didn't solve the issue. I will go the other way of formatting the date in the query. For dynamically populating the data by passing the table name to the query, I will use case statement to switch between queries. It's not the perfect solution, but at least will keep me going. – FullOfLife Apr 05 '17 at 15:00
  • Getting back to this post. – FullOfLife May 19 '17 at 14:35
  • The format of Date column worked when I changed this: `DATEOFBIRTH.setCellValueFactory(new PropertyValueFactory<>("Pdateofbirth"));` To: `DATEOFBIRTH.setCellValueFactory(cellData -> cellData.getValue().dateOfBirthProperty());` – FullOfLife May 19 '17 at 14:45