Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The orders of bean validation default parameters?

I am currently trying to provide a custom validation message using bean validation.

Currently using spring mvc 3.1.1 + apache bean validation.

In my bean, i specify :

@Size(min=1, max=50)
private String title;

And in my messages.properties :

Size.addForm.title=The title must not be empty and must not exceed {1} characters.

From experiment, i found out that :

  • {0} refers to 'title'
  • {1} refers to the max, which is 50
  • {2} refers to the min, which is 1

and it'll be displayed as The title must not be empty and must not exceed 50 characters. which is correct.

But all these are from experiments. I wonder whether there are documentations stating the order of parameters for the default constraints ?

I tried hopefully using Size.addForm.title=The title must not be empty and must not exceed {max} characters. basing on the default ValidationMessages.properties but ends up with NumberFormatException on the {max}. I think it has something to do with the interpolations ?


Update

So, each of these fails independently with NumberFormatException on the {max} :

  • messages.properties : Size.addForm.title=The title must not be empty and must not exceed {max} characters.
  • messages.properties : Size=The title must not be empty and must not exceed {max} characters.
  • messages.properties : javax.validation.constraints.Size.message=The title must not be empty and must not exceed {max} characters.
  • ValidationMessages.properties : Size.addForm.title=The title must not be empty and must not exceed {max} characters.
  • ValidationMessages.properties : Size=The title must not be empty and must not exceed {max} characters.

This is the stacktrace :

java.lang.NumberFormatException: For input string: "max"
    at java.lang.NumberFormatException.forInputString(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at java.text.MessageFormat.makeFormat(Unknown Source)
    at java.text.MessageFormat.applyPattern(Unknown Source)
    at java.text.MessageFormat.<init>(Unknown Source)
    at org.springframework.context.support.MessageSourceSupport.createMessageFormat(MessageSourceSupport.java:151)
    at org.springframework.context.support.ResourceBundleMessageSource.getMessageFormat(ResourceBundleMessageSource.java:281)
    at org.springframework.context.support.ResourceBundleMessageSource.resolveCode(ResourceBundleMessageSource.java:188)
    at org.springframework.context.support.AbstractMessageSource.getMessageInternal(AbstractMessageSource.java:205)
    at org.springframework.context.support.AbstractMessageSource.getMessage(AbstractMessageSource.java:146)
    at org.springframework.context.support.AbstractApplicationContext.getMessage(AbstractApplicationContext.java:1214)
    at org.springframework.web.servlet.support.RequestContext.getMessage(RequestContext.java:571)
    at org.springframework.web.servlet.support.BindStatus.initErrorMessages(BindStatus.java:177)
    at org.springframework.web.servlet.support.BindStatus.getErrorMessages(BindStatus.java:273)
    at org.springframework.web.servlet.tags.form.ErrorsTag.exposeAttributes(ErrorsTag.java:173)
    at org.springframework.web.servlet.tags.form.AbstractHtmlElementBodyTag.writeTagContent(AbstractHtmlElementBodyTag.java:48)
    at org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:102)
    at org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79)

This is the only one that works with the named parameter, it has to be ValidationMessages.properties, and it has to be exactly the key that exists in the default resource bundle by the jsr 303 implementation :

  • ValidationMessages.properties : javax.validation.constraints.Size.message=you know wad, the size must be between {min} and {max}

Basically the current conclusion is, by default, i cannot use named parameters on my specific messages. The named parameter only works when i override the exact key on the default jsr303 resourcebundle && when i use the same default jsr303 resourcebundle file name, which is ValidationMessages.properties

I prefer avoiding having to play with interpolation for now, hence the original question on how to find out that {0} or {1} or {2} refers to what in the documentation.

like image 295
Albert Gan Avatar asked May 05 '12 12:05

Albert Gan


1 Answers

JSR 303 Specification, 4.3.1.1. "Default message interpolation algorithm"

  • 4 - Message parameters are extracted from the message string. Those matching the name of an attribute of the constraint are replaced by the value of that attribute in the constraint declaration.

I read this like: you should use the name of the annotation properties for the message parameter, instead of numbers.

Appendix B "Standard ResourceBundle messages" of the specification shows some examples:

javax.validation.constraints.Min.message=must be greater than or equal to {value}
javax.validation.constraints.Max.message=must be less than or equal to {value}
javax.validation.constraints.Size.message=size must be between {min} and {max}
javax.validation.constraints.Digits.message=numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected)

So it seems that named paramerter are the way you should use. (That {0}, {1} and {2} works too, seems to be a implementation "feature") - But in the end, this is only the behavior of the default message interpolator, the standard defines a way how to replace them by your own.


Update

The Hibernate Validation implementation seams to have an additional feature to format values ${validatedValue:<format>}. -- Maybe that helps you with your java.lang.NumberFormatException

@See Hibernate Validator Reference, Chapter 5.3. MessageInterpolator

like image 194
Ralph Avatar answered Sep 28 '22 05:09

Ralph