Reputation: 73
I am trying to show my SQL table data in my Grid but nothing seems to work. Can you point me where i was wrong?
I found so many ways in the internet, but none have worked for me. Hope you can find the problem and assist me.
I'm using: Vaadin 14 with Spring boot
CustomerService.java
@Component
public class CustomerService {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Customer> findAll() {
return jdbcTemplate.query(
"SELECT ID, FirstName, LastName FROM customer",
(rs, rowNum) -> new Customer(rs.getLong("id"),
rs.getString("First Name"), rs.getString("Last Name")));
}
public void update(Customer customer) {
jdbcTemplate.update("INSERT INTO customer (FirstName,LastName) VALUES(?,?)",customer.getFirstName(),customer.getLastName());
}
}
MainView.Java
public class MainView extends VerticalLayout {
@Autowired
private CustomerService service ;
public Customer customer = new Customer();
private Binder<Customer> binder = new Binder<>(Customer.class);
private TextField firstName = new TextField("First name");
private TextField lastName = new TextField("Last name");
private Grid<Customer> grid = new Grid(Customer.class);
private Button save = new Button("Save", e -> {
try {
binder.writeBean(customer);
saveCustomer();
binder.readBean(new Customer());
} catch (ValidationException ex) {
ex.printStackTrace();
}
});
public MainView(CustomerService service) {
add(
new H1("הוסף לקוח"),
buildForm(),
grid
);
updateGrid(); // update the grid with the sql data
setSizeFull();
}
private void saveCustomer() throws ValidationException {
service.update(customer);
}
private Component buildForm() {
// TextField id = new TextField("ID");
TextField firstName = new TextField("First name");
TextField lastName = new TextField("Last name");
Div errorsLayout = new Div();
binder.forField(firstName)
.bind(
Customer::getFirstName,Customer::setFirstName
);
binder.forField(lastName)
.bind(
Customer::getLastName,Customer::setLastName
);
Button reload = new Button("reload", e ->{
try{
binder.readBean(customer);
} catch (Exception ex) {
ex.printStackTrace();
}
});
// Configure UI components
save.setThemeName("primary");
// Wrap components in layouts
HorizontalLayout formLayout = new HorizontalLayout(grid,firstName,lastName,save,reload);
Div wrapperLayout = new Div(formLayout, errorsLayout);
formLayout.setDefaultVerticalComponentAlignment(Alignment.BASELINE);
wrapperLayout.setWidth("100%");
grid.setColumnReorderingAllowed(true);
return wrapperLayout;
}
private void updateGrid() {
List<Customer> customers = service.findAll();
grid.setItems(customers);
}
The error I get:
There was an exception while trying to navigate to '' with the exception message 'Error creating bean with name 'com.packagename.myapp.spring.MainView': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.packagename.myapp.spring.MainView]: Constructor threw exception; nested exception is java.lang.NullPointerException'
Upvotes: 0
Views: 253
Reputation: 5342
You're never setting your CustomerService
field. Add
this.service = service;
to the beginning of your constructor. Otherwise the member field private CustomerService service
will be null, which is why updateGrid
throws a NullPointerException
.
Also, as a side note, remove the @Autowired
annotation from the member field. Your mixing two different ways of autowiring, one is autowiring fields
@Autowired
private CustomerService service;
public MainView() { ... }
In this case, Spring will automatically set the value for you, and it is not passed as an argument to the constructor. However, Spring sets it after the constructor, so you can not use it in the constructor or any method called from the constructor.
The other way is constructor autowiring, which is what you should be doing. In this case Spring passes the bean to the constructor, but you need to set member fields yourself if needed.
private CustomerService service;
@Autowired
public MainView(CustomerService service) {
this.service = service;
...
}
You don't strictly need the @Autowired
annotation before the constructor, it will work without it, but you can have it there for clarity if you want.
Upvotes: 2