Issue
I am trying to display data in tableView in javafx.
Even though I have used SimpleStringProperty and SimpleIntegerProperty, every time I click "Check Customers" button, I get this error:
Caused by: java.lang.IllegalAccessException: module javafx.base cannot access class application.customer (in module FCR) because module FCR does not open application to javafx.base
at javafx.base/com.sun.javafx.property.MethodHelper.invoke(MethodHelper.java:69)
at javafx.base/com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:197)
... 98 more
This is the code of customer:
public class customer {
private final IntegerProperty ID;
private final StringProperty firstName;
private final StringProperty lastName;
private final StringProperty carPlate;
private final IntegerProperty telephoneNum;
public customer(int ID,String firstName, String lastName, String carPlate, int telephoneNum) {
this.ID = new SimpleIntegerProperty();
this.firstName = new SimpleStringProperty();
this.lastName = new SimpleStringProperty();
this.carPlate = new SimpleStringProperty();
this.telephoneNum = new SimpleIntegerProperty();
setID(ID);
setfirstName(firstName);
setlastName(lastName);
setcarPlate(carPlate);
settelephoneNum(telephoneNum);
}
public final StringProperty firstNameProperty() {
return firstName;
}
public final String getfirstName() {
return firstName.get();
}
public final void setfirstName(String fname) {
firstName.set(fname);
}
public final IntegerProperty IDProperty() {
return ID;
}
public final int getID() {
return ID.get();
}
public final void setID(int iD) {
ID.set(iD);
}
public final StringProperty lastNameProperty() {
return lastName;
}
public final String getlastName() {
return lastName.get();
}
public final void setlastName(String lname) {
lastName.set(getfirstName());;
}
public final IntegerProperty telephoneNumProperty() {
return telephoneNum;
}
public final int gettelephoneNum() {
return telephoneNum.get();
}
public final void settelephoneNum(int tnum) {
telephoneNum.set(tnum);;
}
public final StringProperty carPlateProperty() {
return carPlate;
}
public final String getcarPlate() {
return carPlate.get();
}
public final void setcarPlate(String platenum) {
carPlate.set(platenum);
}
And here is the controller:
public class checkCustomers {
private customersData q = Main.q;
@FXML
private TableView table;
@FXML
private TableColumn firstName;
@FXML
private TableColumn lastName;
@FXML
private TableColumn carPlate;
@FXML
private TableColumn telephoneNumber;
@FXML
public void initialize() {
System.out.println(1);
firstName.setCellValueFactory(new PropertyValueFactory<customer, String>("firstName"));
lastName.setCellValueFactory(new PropertyValueFactory<customer, String>("lastName"));
carPlate.setCellValueFactory(new PropertyValueFactory<customer, String>("carPlate"));
telephoneNumber.setCellValueFactory(new PropertyValueFactory<customer, Integer>("telephoneNumber"));
table.setItems(FXCollections.observableArrayList(q.getAllCustomers()));
}
The module-info.java code is:
module FCR {
requires javafx.controls;
requires javafx.fxml;
requires java.sql;
requires javafx.base;
opens application to javafx.graphics, javafx.fxml;
}
I think I should add something in the module-info can anyone please help?
Solution
Open Your Package to javafx.base
The PropertyValueFactory
class uses reflection to get the named property. You have to grant that class's module (javafx.base
) the necessary access to your code in order for this reflection to work.
Change:
opens application to javafx.graphics, javafx.fxml;
To:
opens application to javafx.graphics, javafx.fxml, javafx.base;
Use a Lambda Expression
The other option is to not use PropertyValueFactory
. That class was most likely created because JavaFX was released before lambda expressions were added in Java 8. It made declaring value factories less verbose, but it has two problems:
- It uses reflection.
- Not necessarily bad, but reflection should be avoided if possible.
- There's no compile-time safety.
- If the needed methods don't exist in the model class, or if the methods return the wrong type, then you'll only find out about it at run-time.
Using a lambda expression avoids both those problems. For example:
lastNameCol.setCellValueFactory(data -> data.getValue().lastNameProperty());
Don't Use Raw Types
Check out the What is a raw type and why shouldn't we use it? Q&A. You're using the raw type of TableView
and TableColumn
. Don't do that; declare the type arguments.
Answered By - Slaw
Answer Checked By - Cary Denson (JavaFixing Admin)