Named parameters in spring/hibernate JSR-303 (Bean validation) localized messages

bean-validation, hibernate-validator, java, localization, spring

Solution

I think that the actual order is alphabetical ("max" is lesser than "min") starting from Spring 3.0.4.

From SPR-6730 discussion (Juergen Hoeller post)

For the first option, Spring-managed field error arguments include the actual constraint annotation attributes in alphabetical order now. So for @Size(min=1,max=5), it'll include the field name as {0} , the max value as {1} , and the min value as {2}

See https://jira.springsource.org/browse/SPR-6730

Problem

I have a simple bean defining user credentials on signup registration form model: ``` public class UserCreds { @Length(min=1, max=50) @NotEmpty private String username; @Email private String email; @NotEmpty @Length(min=1, max=50) private String password; private String passwordConfirm; ... only obvious getters and setters below this line ... } ``` I pass it's instance under "userCreds" model attribute, so i have a following localization bundle: ``` NotEmpty.userCreds.username=Username is required NotEmpty.userCreds.password=Passsword is required Length.userCreds.username=Username length must be between {2} and {1} symbols Length.userCreds.password=Password length must be between {2} and {1} symbols Email.userCreds.email=Ill-formed e-mail address ``` And it works! The problem here: i don't want use this cryptic {N} placeholders, which may change their places occasionally (in bundle above 'max' is binded to {1} and 'min' is binded to {2}, which is at least non-obvious positioning) i wish to use full names of annotaions, as in ``` Length.userCreds.username=Username length must be between {min} and {max} symbols ``` (which is not working - when i try it - am getting `java.lang.IllegalArgumentException: can't parse argument number min` exception) As i could when define message in code (the following example also works): ``` @Length(min=1, max=50, message = "Username length must be between {min} and {max} symbols") @NotEmpty private String username; ``` But when i define it in code i loose my ability to localize the message for different languages. What do? UPDATE 1 After a few hours of poking around debugger in my IDE i found that using the following class: ``` public class BakaMessageSource extends ReloadableResourceBundleMessageSource { @Override protected MessageFormat resolveCode(String code, Locale locale) { /* original implementation * for (String basename : basenames) { List<String> filenames = calculateAllFilenames(basename, locale); for (String filename : filenames) { PropertiesHolder propHolder = getProperties(filename); MessageFormat result = propHolder.getMessageFormat(code, locale); if (result != null) { return result; } } } */ return null; } } ``` With the following spring-servlet.xml declaration: ``` <bean id="messageSource" class="org.eientei.radiorandom.framework.crutchy.BakaMessageSource" p:defaultEncoding="UTF-8" p:alwaysUseMessageFormat="false" > <property name="basenames"> <list> <!-- my application-specific localization bundles --> <value>classpath:messages/root/errorMessages</value> <value>classpath:messages/root/langMessages</value> <value>classpath:messages/user/signupMessages</value> </list> </property> </bean> ``` instead of original ReloadableResourceBundleMessageSource actually helps to get localized messages with named parameters. But i guess swapping classes around at that point is not a proper solution. Which one would be? UPDATE 2 I am such an idiot. I forgot in-code message and thought it got interpolated properly. Geez. So, alphabetical ordering... guess i can't ask for more.

Original source