trebor
trebor

Reputation: 1003

Spring MVC form validation messages not loading

I'm trying to define error messages in a resource file, but I can't seem to get them to load so I can use them in my controller.

My servlet-context.xml file:

<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <beans:property name="basename" value="classpath:messages" />
</beans:bean>

My form:

public class LoginForm {
    @NotEmpty
    private String username;
    // getters and setters
}

My messages.properties file (in the root of my source folder, so it gets compiled to the root of my classes folder):

NotEmpty.loginForm.username=test1
NotEmpty.username=test2
NotEmpty.java.lang.String=test3
NotEmpty=test4

My controller:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@Valid LoginForm form, BindingResult result) {
    if (result.getFieldErrors().size() > 0) {
        FieldError firstError = result.getFieldErrors().get(0);
        System.out.println(firstError.getDefaultMessage());
    }
    // ...
}

However, the output of the getDefaultMessage call is never what I define in my resource file! It is always may not be empty (the default).

I've tried a variety of different entries in my context file but it seems like it's not loading the resource file. What am I doing wrong?

Upvotes: 1

Views: 3700

Answers (4)

Saravanan Sagadevan
Saravanan Sagadevan

Reputation: 1

I spent some time to fix this issue, I done a following changes, now it is working fine in Spring 4.0 MVC and Hibernate 4.1.9

1.put messages under source folder.

  1. If ReloadableResourceBundleMessageSource is not working change to

    class="org.springframework.context.support.ResourceBundleMessageSource">

  2. changes property like '<'property name="basename" value="messages"/>

  3. In Message.properties file, the key should be in the following format.

    NotEmpty.userForm.userId

    userForm-->Model class name.
    

(If your Model class name is UserForm, then it should
be mentioned as userForm)

    userId--> attribute of userForm class

Upvotes: 0

trebor
trebor

Reputation: 1003

Unfortunately it looks like a MessageSource must be defined and then used in the appropriate Java class. The getDefaultMessage() method doesn't appear able to read from message properties.

In a component-scanned class:

@Autowired
private MessageSource messageSource;
public String getMessage(FieldError field) {
    return messageSource.getMessage(field, null);
}

This will iterate through all possibilities in the message properties files and then--if nothing is found--falls back on the getDefaultMessage() results.

Additionally I updated my servlet-context.xml file to define my messageSource with the basename value of /WEB-INF/classes/messages, as opposed to what I had in my question above.

Upvotes: 0

yname
yname

Reputation: 2245

First idea:

Try to rename property keys from NotEmpty.loginForm.username to NotEmpty (Just to check if messageSource works correctly). If still not working there is

Second idea:

Where do you perform scanning of components? Assume that you have two spring configurations: applicationContext.xml (or other name) and servlet-context.xml.

If you have such structure <context:component-scan base-package="by.company.app" /> in applicationContext than your controllers have no defined messageSource - so it cannot load customized messages. It is because @Controller bean is in one spring context, MessageSource bean - in another. (To check this you can simple declare @Autowired MessageSource messageSource field in controller and see in debug is it null or not) In that case you can modify component-scan in applicationContext to:

<context:component-scan base-package="by.company.app">
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

and add following configuration to servlet-context.xml:

<context:component-scan base-package="by" use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

Hope this helps

Upvotes: 0

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279920

According to this documentation, all you need is to put a properties file called ValidationMessages.properties at the root of your project classpath.

You can then add properties with the following format

org.hibernate.validator.constraints.NotEmpty.message=Default message, can not be empty 
NotEmpty.ClassName.fieldName=fieldName can not be empty.

where ClassName is the name of your class and fieldName is the name of the field of that class.

You might need to do some configuration to set the correct MessageInterpolator, but I think the default one will do what you need.

Upvotes: 1

Related Questions