I am trying to create a form object extending Formlayout with binder inside. So I already bound my textfields this way
// Bind fields to entity properties by naming convention
binder = new Binder<>(Item.class);
binder.forField(price)
.withConverter(new StringToBigDecimalConverter(new BigDecimal(10.00), "Price must be in ##.## format"))
.bind(Item::getPrice, Item::setPrice);
binder.forField(name).bind(Item::getName, Item::setName);
binder.forField(description).bind(Item::getDescription, Item::setDescription);
name, description and price are all textfields they are all string types except the price which is BigDecimal. I am having all this code in the form class constructor. When I am trying to initialize my binder by calling
binder.setBean(new Item()
Here is the exception:
SEVERE: Servlet.service() for servlet [dispatcherServlet]
in context with path [] threw exception [com.vaadin.server.ServiceException: java.lang.NullPointerException: value cannot be null]
with root cause
java.lang.NullPointerException: value cannot be null
it throws
NullPointerException . I used to bind this way in Vaadin 7 without any issues. I have another form where I don’t explecitly bind my fields I do bind the by calling this on the binder object
binder.bindInstanceFields(CustomerForm.this);
This works fine for the other view where I get the exception which is the item view I need to bind manually since I have a BigDecimal field.
The problem is that the bean’s values are null, and TextField in Vaadin 8 can’t handle null and will fail with NPE as above mentioned. Since I believe a lot of programmers will bump into this, I have created a bug for this:
https://github.com/vaadin/framework/issues/8664 The bug report also contains a workaround.
I had the same NPE issue with
StringToIntegerConverter . Next line solved my problem.
binder.withConverter(Integer::valueOf, value -> (value == null) ? "" : String.valueOf(value), "Must be a number"))
In your case this should pass without NPE:
binder.forField(price)
.withConverter(value -> value.isEmpty() ? new BigDecimal("10.00") : new BigDecimal(value),
value -> value == null ? "" : value.toString(),
"Price must be in ##.## format")
.bind(Item::getPrice, Item::setPrice);
I had the same NPE issue with StringToBigDecimalConverter.
The solution of C.Berg doesn’t work for me because it doesn’t handle numbers in non english format.
The workaround of Martin Vyšný (https://github.com/vaadin/framework/issues/8664) is the best solution because it uses a NumberFormat with the current locale.
In your case it would look as follows:
binder.forField(price)
.withNullRepresentation("")
.withConverter(new StringToBigDecimalConverter("Price must be in ##.## format"))
.bind(Item::getPrice, Item::setPrice);
This results in an empty field, if the price is null and returns null, if the field is empty.