I’m a bit confused about these 2 couples of methods:
- getbean and setBean
- readBean and writeBean
In the following scenario which one should I use if I want to populate my fields with bean’s values and later retrieve the bean with its fields updated from the user interface ?
If a bean is set to the binder, is this bean automatically updated when the user performs changes in the UI ?
- getBean / setBean is “unbuffered” mode
- readBean / write Bean is “buffered” mode.
With setBean, if you modify the value of a bound textfield then the value of the bean property is changed.
With readBean, if you modify the value of a bound textfield then the value of the bean property is NOT changed.
Then you have to call writeBean to write new values in the bean.
Yes (if you use setBean method)
Is there any guide about these 2 modes ? It is rather confusing and the javadoc is not really clear about it…
I would like to know when should I use one mode rather than the other.
I have played a bit with the binder to try to figure myself how it works and I have the folowing 2 scenarios:
- get/set – unbuffered - stateful
- the binder keeps the state of the model
- the validation occurs after any change in the fields
- no further validation is done when trying to get the bean, so the validate() and isValid()methods shoud be called manually when we need to prevent the model bean to be retrieved by an external actor.
- the model managed by the binder is updated whenever it is possible
[code]
Binder binder = new Binder<>();
binder.forField(x).bind(…);
binder.setBean(aBean);
save.addClickListener(c → {
binder.validate()
if (binder.isValid()) {
presenter.saveUpdatedModel(binder.getBean());
}
})
[/code]2) read/write – buffered - stateless
- the binder doesn’t keep any trace of the mode
- the validation is triggered by the writeBean() method which is the only way (with writeBeanIfValid) to retrieve the model from the form
Binder<Bean> binder = new Binder<>();
this.model = aBean;
binder.forField(x).bind(...);
binder.readBean(this.model);
save.addClickListener(c -> {
try {
binder.writeBean(this.model);
presenter.saveUpdatedModel(binder.getBean());
} catch( ValidationException v ) {
//this.model is rollbacked to the previous state
}
})
But now I don’t know when it is best to use one flavor rather another… The first one is less cluttered (no exception) but a dev can easily be confused and forget about the validation part…
The second flavor is more verbose and requires us to maintain our model state somewhere, but will enforce the validation…
I’ll try to explain what i understand :).
In the 2 modes:
- When you modify a field, this field is validated and an error is displayed
In unbuffered mode:
- When you modify a field, Bean level validation is done (if you want to validate date from and to)
In buffered mode:
- When you modify a field, Bean level validation is NOT done but it’s done when writeBean is called.
If you want to display errors immediately (bean level errors) then you should use unbuffered mode.
In buffered mode, you should use readBean/writeBean (or writeBeanIfValid)
In unbuffered mode, you shoudl use setBean/getBean/validate (or isValid) /removeBean
if you use a function in the “wrong” mode then the result will be unexpected (for example getBean = NULL with readBean, removeBean is not “working” after readBean …)
validate does the same thing as isValid (but isValid returns true or false instead validationException). You have the same behaviour with writeBean and writeBeanIfValid.
The only guide you have is there: https://vaadin.com/docs/-/part/framework/datamodel/datamodel-forms.html
When using the setBean method, the business object instance will be updated whenever the user changes
the value in any bound field. If some other part of the application is also using the same instance,
then that part might show changes before the user has clicked the save button.
Bean level validation can only be performed once the bean has been updated.
This means that this functionality can only be used together with setBean.
You need to trigger validation manually if using readBean and writeBean.
I use readBean and writeBean to avoid side effects (get some uncommited changes in my application) and because there is no “discard” function when you use setBean.
Merci / Thanks
I’m really confused about the field level / bean level validation…
About “validate does the same thing as isValid (but isValid returns true or false instead validationException)”
While doing some experimentation, I found that isValide() doesn’t work until a call to validate has been performed. Maybe I was confused by doing to much tests: in the code it really looks like the validation is performed on a ‘isValid()’ call.
I’m a bit unsatisfied with this Binder class: it looks very simple, but then there is a lot of subtility poorly described in the documentation and that can lead to unexpected behaviors. And it is also hard to explain to other co-worker how to use this core element. I’m a bit affraid of nasty bugs caused by a missconfiguration of the binder…
I should write a small app demonstrating the two ways for my own understanding !
When you call validate or isValid, the field validation (validator added on field) is done for each field then if there is no error then validate the bean (validator added on the binder). (you can see the javadoc of validate)
I didn’t use validate (i’m using writeBeanIfvalid), I’ve just check the code of validate and isValid (and the code called the same functions) so you may be right.