0

In my Vaadin (v.23.2.6) application I have a form tied up to Filter class which has 5 attributes. All of them are optional, i.e. user can leave the blank.

 public FilterPanel(ApiBookUtils api) {
    this.api = api;
    this.authorField = new ComboBox<Author>("Author Name");
    this.countryField = new ComboBox<>("Country");
    this.countryField.setReadOnly(true);
    this.fromYear = new IntegerField ("From");
    this.fromYear.setWidth("60px");
    this.toYear = new IntegerField ("To");
    this.toYear.setWidth("60px");
    this.binder = new Binder(Filter.class);
    this.setModal(true);
    this.setCloseOnOutsideClick(false);
    this.setCloseOnEsc(true);
    buildDialog();
}

private void buildDialog() {
    bindFields();
    addFields();
    setDialogListeners();
    setDialogItems();
}
private void bindFields() {
    this.binder.bind(authorField, Filter::getAuthor, Filter::setAuthor);
    this.binder.forField(countryField).bind(Filter::getCountry, Filter::setCountry);
    this.binder.forField(fromYear).bind(Filter::getFromYear, Filter::setFromYear);
    this.binder.forField(toYear).bind(Filter::getToYear, Filter::setToYear);
    this.binder.forField(postingDateField).bind(Filter::getPostingDate, Filter::setPostingDate);
    this.binder.forField(tagField).bind(Filter::getTags, Filter::setTags);
}

I am getting getting exception if IntegerField is left blank.

com.vaadin.flow.data.binder.BindingException: An exception has been thrown inside binding logic for the field element [label='From'] at com.vaadin.flow.data.binder.Binder$BindingImpl.execute(Binder.java:1570) ~[flow-data-23.2.5.jar:23.2.5] at com.vaadin.flow.data.binder.Binder$BindingImpl.writeFieldValue(Binder.java:1427) ~[flow-data-23.2.5.jar:23.2.5] at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na] Caused by: java.lang.NullPointerException: null at com.vaadin.flow.data.binder.Binder$BindingImpl.lambda$writeFieldValue$5169480d$1(Binder.java:1431) ~[flow-data-23.2.5.jar:23.2.5]

Does anybody know how to make binder to accept empty field and set up default value in the bean?

Gary Greenberg
  • 1,084
  • 8
  • 14
  • Can you check in your code whether Filter::setFromYear accepts null value? – Tatu Lund Nov 14 '22 at 07:36
  • My methods do accepts null values. If an error occurs in my method, Exception stack trace will show me the line of MY code. It doesn't happen here. Stack trace explicitly said that " An exception has been thrown inside binding logic". I did review all javadoc for IntegerField, NumberField, Binder and nowhere found any methods that will allow accepting null values. IMHO it is a bug in the binder. – Gary Greenberg Nov 15 '22 at 05:16
  • But according to stack trace NPE is thrown when your setter is being applied. Based on the information you have shared, setter throwing the NPE and Binder failing due that is pretty much the only option. You did not share full stacktrace though. – Tatu Lund Nov 15 '22 at 06:04

2 Answers2

0

I found the workaround the bug in the Binder. Apparently, it does not process primitive types correctly. I have replaced int fields in my bean with Integer object and exception was gone.

Gary Greenberg
  • 1,084
  • 8
  • 14
-1

If IntegerField is empty, the value is by definition null. If your business logic throws NPE due this, Binder will fail. You can set the binding to convert null value to your presentation by using withNullPresentation(defaultValue).

this.binder.forField(fromYear)
    .withNullPresentation(0)  // e.g. interpret null as zero
    .bind(Filter::getFromYear, Filter::setFromYear);
Tatu Lund
  • 9,949
  • 1
  • 12
  • 26
  • No it didn't work. I added .withNullPresentation(0) but it was still throwing the same exception. I did find the solution, though. See my answer below. – Gary Greenberg Nov 16 '22 at 03:18