0

I'm using Hibernate Validator to validate the input fields in my form. Ideally I'd want to show an error message next to each field when there is a problem with that field.

In the register form I ask for a password and to repeat the password and I want to make sure they match. Using this question I was able to implement this. The problem with this is of course that the validation happens at the class level which means the error message is only shown when I do:

<form:errors path="*" />

I thought this would be fine, I'll be doing validation client-side as well and I can do the inline approach there, if people have turned off JS, it's not that bad that I have a group element to show the errors. The problem with this approach is that I have to be able to say for instance:

'Name' field cannot be empty
'Email' field is invalid

As I am making this application with i18n in mind, I can't hard code the field names like 'Email' and 'Name' so I have the following in my User entity for validation ({fieldEmpty} is just a string that says 'cannot be empty'):

@Email(message = "{register_EmailInvalid}")
@NotBlank(message = "\"{register_EmailField}\" {fieldEmpty}")
private String email;
@NotBlank(message = "\"{register_NameField}\" {fieldEmpty}")
private String name;
@NotBlank(message = "\"{register_FirstNameField}\" {fieldEmpty}")
private String firstName;
@NotBlank(message = "\"{register_PasswordField}\" {fieldEmpty}")
private String password;
@NotBlank(message = "\"{register_PasswordRepeatField}\" {fieldEmpty}")
private String passwordRepeat;

This picks up the correct value for the field name according to the locale setting of the user but it also means I have to duplicate the register_EmailField, register_NameField, ... in my regular messages.properties and my ValidationMessages.properties.

The field names are at the moment all in the ValidationMessages.properties and they are not being used when the page loads, so the form shows the labels always as my default locale.

In the picture below you can see that everything is in Dutch, except for the labels of my form. How should I approach this, am I missing a much easier way to accomplish this? Can I link the class-level validation message to a specific field?

enter image description here

If I put the form label messages in my messages_nl.properties as well then it works of course but I don't want to have those messages duplicated.

2 Answers 2

1

You only need to configure the LocalValidationFactoryBean

<mvc:annotation-driven validator="validator" />

<bean id="validator"
  class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
     <property name="validationMessageSource" ref="messageSource" />
</bean>

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>WEB-INF/i18n/messages</value>
            <value>WEB-INF/i18n/application</value>     
            <value>classpath:ValidationMessages</value>
                           ....
        </list>
    </property>
    <property name="fallbackToSystemLocale" value="false"/>
</bean>
Sign up to request clarification or add additional context in comments.

3 Comments

this doesn't seem to work. Should this solution basically allow me to use messages from any properties file? Seems like it still only allows me to read from the ValidationMessages file when validating.
How do you do the validation? requestHandlerMethod(@Valid Command command, BindingResult bindingResult) ?
my apologies, I had forgotten to remove my other mvc:annotation-driven /> element and just copied yours, which meant I had it twice. Now that I've removed mine it works great, thanks!
1

You could use your messages bundle as resource bundle for Hibernate Validator instead of the default ValidationMessages bundle.

To do so, set up your validator using a custom resource bundle locator like this:

Validator validator = Validation.byDefaultProvider()
    .configure()
    .messageInterpolator(
            new ResourceBundleMessageInterpolator(
                    new PlatformResourceBundleLocator( "messages" )
            )
    )
    .buildValidatorFactory()
    .getValidator();

2 Comments

this looks like what I need, I'm only a beginner though, where exactly do I put this code?
It depends on how you bootstrap your validator. You could e.g. expose a validator created like this via a factory method. But assuming you're are working with LocalValidationFactoryBean Ralph's solution looks more suitable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.