0

I am working with Spring 4.0.7 and Spring Web Flow 2.4.0

I have the following (I am working with JSR 349):

For an entity:

@Min(value=1, message="{person.age.min}",groups={PersonRegistrationCheck.class})
@Max(value=115, message="{person.age.max}",groups={PersonRegistrationCheck.class})
@NotNull(message="{field.null}",groups={PersonRegistrationCheck.class})
@Column(name="age", nullable=false, length=3)
@XmlElement
public Integer getAge() {
    return age;
}

In the ValidationMessages.properties file

person.age.max = Invalid data '${validatedValue}', the maximum value allowed is {value}
person.age.min = Invalid data '${validatedValue}', the minimum value allowed is {value}

In some @Configuration

@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean(ReloadableResourceBundleMessageSource messageSource){

    LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
    localValidatorFactoryBean.setValidationMessageSource(messageSource);

    MessageSourceResourceBundleLocator msrbl = new MessageSourceResourceBundleLocator(messageSource); 
    ResourceBundleMessageInterpolator rbmi = new ResourceBundleMessageInterpolator(msrbl);
    localValidatorFactoryBean.setMessageInterpolator(rbmi);

    return localValidatorFactoryBean;
}

Through Spring MVC it works perfectly fine:

<tr>
    <td><spring:message code="person.form.age"/></td>
    <td><form:input path="age" size="40"/></td>
    <td><form:errors path="age" cssClass="error"/></td>
</tr>

If I put an invalid value how 500 I get

Invalid data 500, the maximum value allowed is 115

I can see the invalid data and the maximum value allowed.

Until here all is OK..

Note: is not necessary do a special injection about LocalValidatorFactoryBean for Spring MVC

The problem is with Spring Web Flow.

Note: is necessary do a special injection about LocalValidatorFactoryBean for Spring Web Flow

Here its configuration:

@Autowired
private LocalValidatorFactoryBean localValidatorFactoryBean;

@Bean
public FlowBuilderServices flowBuilderServices() {
    return getFlowBuilderServicesBuilder()
            .setViewFactoryCreator(mvcViewFactoryCreator())
            .setConversionService(conversionService())              
            .setValidator(localValidatorFactoryBean)
            .setDevelopmentMode(true)   
            .build();
}

Above is practically almost the same according with spring-webflow-samples / WebFlowConfig

In the flow definition

<view-state id="start" 
        view="person.flow.form.register" 
        model="person"
        validation-hints="'com.manuel.jordan...PersonRegistrationCheck'"  >
    <transition on="submit" to="address" bind="true" validate="true" >
        <evaluate expression="personAction.savePerson(flowRequestContext)" />
    </transition>
    <transition on="cancel" to="end" bind="false" validate="false"/>
</view-state>

Again in the .jsp file

<tr>
    <td><spring:message code="person.form.age"/></td>
    <td><form:input path="age" size="40"/></td>
    <td><form:errors path="age" cssClass="error"/></td>
</tr>

Note: It is other or new .jsp file, it to work for Spring Web Flow. Therefore one to work through Spring MVC and other for SWF. It for testing purposes

Ok the problem:

Again If I put an invalid value how 500 I get

Invalid data $validatedValue, the maximum value allowed is value

Observe: We can't see, the invalid data (remains with $validatedValue) and value remains how static.

Therefore:

  • Spring MVC shows: Invalid data 500, the maximum value allowed is 115
  • SWF shows: Invalid data $validatedValue, the maximum value allowed is value

Note: Even If use the following, all go wrong yet.

@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean(ReloadableResourceBundleMessageSource messageSource){

    LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
    localValidatorFactoryBean.setValidationMessageSource(messageSource);

    //MessageSourceResourceBundleLocator msrbl = new MessageSourceResourceBundleLocator(messageSource); 
    //ResourceBundleMessageInterpolator rbmi = new ResourceBundleMessageInterpolator(msrbl);
    //localValidatorFactoryBean.setMessageInterpolator(rbmi);

    return localValidatorFactoryBean;
}

What is wrong or missing?

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158

1 Answers1

0

Using the booking-mvc sample I could confirm all works as expected. I tried both ValidationMessages.properties with default LocalValidatorFactoryBean (i.e. no custom interpolator, just relying on Hibernate validator) as well as "/WEB-INF/messages.properties" with a custom ResourceBundleMessageInterpolator pointing to the ResourceBundleMessageSource.

Several notes on the above:

  • setValidationMessageSource and setMessageInterpolator on LocalValidatorFactoryBean are mutually exclusive. The javadoc clearly states that.

  • ValidationMessages.properties is the default (JSR-303) bean validation mechanism. Once you set a custom MessageInterpolator, ValidationMessages.properties is no longer used.

  • Support for ${validatedValue} seems to be something that's available with Hibernate validator version 5+, i.e. it's not available in 4.3.

  • in Web Flow we also look at messages.properties in the flow directory. Need to make sure there aren't any error codes that are overriding the JSR-303 resolved violation messages.

With those in mind everything seems to work fine.

Rossen Stoyanchev
  • 4,910
  • 23
  • 26