Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Web MVC validation by Hibernate Validator doesn't draw Errors in BindingResult

I've been using Hibernate Validator in my Spring project. I'm about to validate my JUser Object automatically. i.e, I want Spring to validate the Object and set errors in BindigResult. But It doesn't work.

pom.xml

<properties>
    <spring.version>4.3.5.RELEASE</spring.version>
    <spring.security.version>4.0.2.RELEASE</spring.security.version>
    <hibernate.version>4.3.11.Final</hibernate.version>
    <validation-api.version>1.1.0.Final</validation-api.version>
    <hibernate-validator.version>5.4.0.Final</hibernate-validator.version>
</properties>
....

applicationContext.xml

...
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<context:annotation-config />
<context:component-scan base-package="my.project.controller" />
<mvc:annotation-driven validator="validator">
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages"/>
</bean>

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
</bean>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
    <property name="validator" ref="validator"/>
</bean>
<bean id="localeResolver"
      class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
    <property name="defaultLocale" value="en" />
</bean>

JUser.java

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;

@Entity
public class JUser implements Officeable {

   @Id
   private Long id;

   @Column(unique = true, nullable = false)
   private String username;

   private String password;

   @NotEmpty
   private String firstName;

   @NotEmpty
   private String lastName;
   private String tel;
}

UserController.java

import javax.validation.ConstraintViolationException;
....

@RequestMapping(value = "/update", method = RequestMethod.POST)
public String update2(HttpServletRequest request, Model model, @ModelAttribute("user") @Valid JUser user, BindingResult result) {
    if (!result.hasErrors()) {
        System.out.println("binding result has no errors for user ");
        try {
            JUser updated = userService.update(user);
            model.addAttribute("user", updated);
        } catch (MessageException | DataIntegrityViolationException ex) {
            result.reject("user", ex.getMessage());
        } catch (ConstraintViolationException cvex) {
            for (ConstraintViolation cv : cvex.getConstraintViolations()) {
                result.rejectValue(cv.getPropertyPath().toString(),cv.getMessageTemplate() , cv.getMessage());
            }
        }
    }
    return "user/manage";
}

As you see in the above controller method I want Spring to validate the user Object and set errors in BindigResult. But It does not work.
For example when user has empty firstName I face the output:

output:
binding result has no errors for user 

and I have to catch hibernate thrown exceptions by hand:

 ConstraintViolationException: may not be empty ...

more description. I've used String @Validated annotation and It did not work as well. I've read more than ten related stackoverflow questions and they didn't solved my problem.

like image 288
Dariush Jafari Avatar asked Mar 07 '17 21:03

Dariush Jafari


2 Answers

First thing, can you test if validate is working after adding below code?

pom.xml
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.2.4.Final</version>
    </dependency>

@Bean // in configuration
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        return validatorFactory.getValidator();
    }


@Autowired //in controller
private Validator validator;

public <T> void validate(T t) {
    Set validate = this.validator.validate(t);
    if(!validate.isEmpty()) {
        throw new RuntimeException();
    }
}

If this works, then can suggest you further to simplify it.

like image 115
krmanish007 Avatar answered Nov 16 '22 21:11

krmanish007


As per spring-mvc-4.3.xsd

The bean name of the Validator that is to be used to validate Controller model objects. This attribute is not required, and only needs to be specified if a custom Validator needs to be configured. If not specified, JSR-303 validation will be installed if a JSR-303 provider is present on the classpath.

I don't see you wrote any custom validator so you can change

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

to support the default JSR-303

<mvc:annotation-driven />

Example: Spring 3 MVC and JSR303 @Valid example


Update 1

Could you also try removing validation-api.version

This transitively pulls in the dependency to the Bean Validation API (javax.validation:validation-api:1.1.0.Final).

like image 1
Pavan Kumar Jorrigala Avatar answered Nov 16 '22 20:11

Pavan Kumar Jorrigala