Vaadin beanvalidation using @Digits

Hey everyone,

For the next step in my project I have to use validation. I checked out the documentation and almost all annotations work out of the box which is very nice. For some reason however the validation does not seem te work with the @Digits annotation.
So I want to use the @Digits annotation so I can specify how many fraction digits are used.
Example a: up to nine digits ea; 123456789 with no fraction

@Digits(integer = 9, fraction = 0)`
private BigDecimal test;

Example b: up tow two digits ea; 12.11 with up to a maximum of two fraction numbers.

@Digits(integer = 2, fraction = 2)`
private BigDecimal test;

Then I bind the variable like this:

binder.forField(dossierNo).withConverter(new StringToBigIntegerConverter("")).bind("dossierNo");

Unfortunately it doesn’t do anything at all when I input invalid numbers.
Does anyone have an idea why it’s not working and on how to make it work?

Kind regards,

Sjoerd Brauer

Hi,

I don’t have an idea if the @Digits annotation specifically is supposed to work or not, but generally JSR 303 bean validation annotations are only checked if you use a BeanValidationBinder and binder.bindInstanceFields way of binding. See more here: https://vaadin.com/docs/v13/flow/binding-data/tutorial-flow-components-binder-beans.html

-Olli

Hi Olli,

Thanks for replying. I’m using the BeanValidationBinder.
I cannot use the bindInstanceFields because I use BigDecimal’s so I need to use the StringToBigDecimal converter.
If I don’t do that I get an error that it doesn’t accept pure BigDecimal’s

Kind regards,

Hi,

for that, you can use a partially configured binding:

beanValidationBinder.forMemberField(dossierNo).withConverter(new StringToBigIntegerConverter(""));

(leave out the .bind("dossierNo") from the end)
and after that, call beanValidationBinder.bindInstanceFields();

You can look at the javadocs of forMemberField for some more info: https://vaadin.com/api/platform/13.0.6/com/vaadin/flow/data/binder/Binder.html#forMemberField-com.vaadin.flow.component.HasValue-

-Olli

Hi Olli,

I tried doing that, now it doesn’t throw errors when I bind BigDecimals which is very nice.
The validation for the @Positive annotation works.

Unfortunately the @Digits annotation still doesn’t work.

Kind regards,

As far as I understand, the JSR-303 validations themselves are based on your environment’s ValidationProvider (they are not coded into the Flow framework). So it might be that your implementation doesn’t support @Digits. You can read more here: https://github.com/vaadin/flow/blob/master/flow-data/src/main/java/com/vaadin/flow/data/validator/BeanValidator.java and here: https://github.com/beanvalidation/beanvalidation-api/blob/master/src/main/java/javax/validation/Validation.java#L25

-Olli

Hi Olli,

I Checked the documentation of JSR-303 and it includes the @Digits annotation.
See: https://beanvalidation.org/1.0/spec/

Kind regards,

Sure, but that doesn’t tell about the exact ValidationProvider you’re using.

-Olli

Yes you are right,

I checked and we use JSR-380 so it should be included.

Kind regards,

Then I recommend you should debug the apply method of BeanValidator and see what happens there: https://github.com/vaadin/flow/blob/master/flow-data/src/main/java/com/vaadin/flow/data/validator/BeanValidator.java#L124

-Olli

Hey Olli,

I did some more experimenting, I found out that the @Digits annotation doesn’t work for BigInteger when using a textfield.
A BigInteger should never be able to convert in any case in my opinion, so the text field should give a message or something. I guess what the converter does is cut off what’s inputted after the comma. That’s good but then the user doesn’t know that what he/she inputted is wrong.

I actually used a BigInteger instead of a BigDecimal so I provided some wrong intel, sorry for that. It’s working now with BigDecimal but not the way I would like it to work…

Kind regards,

Hi,

you can of course create your own Converter if the default one doesn’t work for your needs.

-Olli

Hey Olli,

Thanks for the advice, I now use the code found below which works.
This code has been inspired by https://vaadin.com/forum/thread/17649839/17649927

public class DoubleToBigDecimalConverter implements Converter<Double, BigDecimal> {
    @Override
    public Result<BigDecimal> convertToModel(Double presentation, ValueContext valueContext) {
        return Result.ok(BigDecimal.valueOf(presentation));
    }

    @Override
    public Double convertToPresentation(BigDecimal model, ValueContext valueContext) {
        return model.doubleValue();
    }
}

Nice!