6

I am using Spring 4. My form contains the following variables:

@NotNull
@Email
private String email;
@NotNull
private String firstName;
@NotNull
private String lastName;
@Digits(fraction = 0, integer = 10)
private String phoneNo;
@NotNull
private String role;

My controller:

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public ModelAndView add(@ModelAttribute("user") @Valid UserBean user, BindingResult result) {
    String message;
    if (result.hasErrors() && user != null)
        return new ModelAndView("userAdd");
    else {
        userService.addUser(user);
        message = "Successfully added user";
    }
    return new ModelAndView("success", "message", message);
    }

    @RequestMapping(value = "/register")
    public ModelAndView register(@ModelAttribute("user") UserBean user, BindingResult result) {
    List<String> roles = new ArrayList<String>();
    roles.add("Receiver");
    roles.add("Resolver");
    roles.add("Logger");
    Map<String, List<String>> model = new HashMap<String, List<String>>();
    model.put("roles", roles);
    return new ModelAndView("userAdd", "model", model);
    }
}

My jsp:

<c:url var="userAdd" value="user/add.do" />
    <sf:form method="post" action="${userAdd}" modelAttribute="user">
        <table>
            <tr>
                <td>First Name</td>
                <td><sf:input path="firstName" /><br /> <sf:errors
                        path="firstName" cssClass="error" /></td>
            </tr>
            <tr>
                <td>Last Name</td>
                <td><sf:input path="lastName" /><br /> <sf:errors
                        path="lastName" cssClass="error" /></td>
            </tr>
            <tr>
                <td>Email</td>
                <td><sf:input path="email" /><br /> <sf:errors
                        path="email" cssClass="error" /></td>
            </tr>
            <tr>
                <td>Phone No.</td>
                <td><sf:input path="phoneNo" /><br /> <sf:errors
                        path="phoneNo" cssClass="error" /></td>
            </tr>
            <tr>
                <td>Role</td>
                <td><sf:select path="role" items="${model.roles}" /><br /> <sf:errors
                        path="role" cssClass="error" /></td>
            </tr>
            <tr>
                <td><input type="submit" value="Submit" /></td>
            </tr>
        </table>
    </sf:form>

When I leave the the inputs blank, the form does not validate and does not throw any error. The BindingResult does not have any errors in it.

My libraries are: Libraries

My dispatcher-serlvet.xml is:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- Scans for annotated @Controllers in the classpath -->
    <context:component-scan base-package="com.mj.cchp.controller">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
    <bean id="myBeansValidator"
        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
    <mvc:annotation-driven validator="myBeansValidator" />
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
</beans>

My applicationContext is:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- Scans for annotated @Controllers in the classpath -->
    <context:component-scan base-package="com.mj.cchp">
        <context:exclude-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
        <property name="url" value="jdbc:db2://172.16.2.181:60000/CCHP" />
        <property name="username" value="db2inst1" />
        <property name="password" value="db2inst1" />
    </bean> 
</beans>

My web.xml is:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>CCHP</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/application-context.xml</param-value>
    </context-param>
    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>
3
  • Do you have a JSR-303 implementation on your classpath? I.e something like hibernate-validator, without it the annotations do nothing. Commented Jan 31, 2014 at 11:45
  • I have included them. I have updated my answer with a snapshot of my libraries. Commented Jan 31, 2014 at 11:58
  • and your configuration? Commented Jan 31, 2014 at 12:13

10 Answers 10

11

You need to add

<bean id="myBeansValidator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

and

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

and

    <!-- Hibernate Validator -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.2.0.Final</version>
    </dependency>

Should work!

Sign up to request clarification or add additional context in comments.

5 Comments

On doing that I am getting the following error: Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.validation.beanvalidation.LocalValidatorFactoryBean] for bean with name 'myBeansValidator' defined in ServletContext resource [/WEB-INF/dispatcher-servlet.xml]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: javax/validation/ValidatorFactory Caused by: java.lang.ClassNotFoundException: javax.validation.ValidatorFactory
It's not possible. javax.validation.ValidatorFactory is in the jar validation-api and is included with hibernate-validator. Which tool do you use to build your project? Maven? If so, clean install should work to import the new librairies. i.imgur.com/F2R8QDb.png
I got the problem. I was not using any tool. I was manually adding dependencies. So the validation-api jar was not included. But why wasn't the class taken from javaee-api jar which has it included.
This fixed my problem. But I'm not sure why I have to do this as the schema documentation says:"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 explicitly 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."
"will be installed if a JSR-303 provider is present on the classpath". Maybe you didn't have a JSR-303 provider in your classpath
5

I had a similar problem and in my case it was sufficient to just add dependency for hibernate validator: org.hibernate:hibernate-validator:5.2.4.Final.

The validation is done by LocalValidatorFactoryBean bean and documentation about it comes handy (here).

Yet at the same time it is worth mentioning that you do not have to instantiate LocalValidatorFactoryBean explicitly as long as you use @EnableWebMvc annotation : http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config-validation

By default use of @EnableWebMvc or automatically registers Bean Validation support in Spring MVC through the LocalValidatorFactoryBean when a Bean Validation provider such as Hibernate Validator is detected on the classpath.

Hope this helps.

Comments

2

I faced the same problem. I resolved by adding below statement in dispatcher-serlvet.xml file.

<mvc:annotation-driven />

Comments

1

I'm not sure whether you have found ways to fix this. I am facing the same issue as well. and I managed to solve it. The problem with my setting is totally manual and I'm doing big mistake by placing the whole hibernate-validator-5.1.3.Final-dist.zip inside lib folder.

So what I did is I get this 6 files inside "hibernate-validator-5.1.3.Final-dist.zip" in dist folder and place this with web app lib.

  • classmate-1.0.0.jar
  • hibernate-validator-5.1.3.Final.jar
  • javax.el-2.2.4.jar
  • javax.el-api-2.2.4.jar
  • jboss-logging-3.1.3.GA.jar
  • validation-api-1.1.0.Final.jar

This fixed my issue.

Comments

1

i also faced the same issue where my entire code was properly written.

The problem was the different version of jar files that i was using .

I had hibernate-validator-cdi- 5.0.7.Final and hibernate-validator-6.0.2.Final.

Just make sure your jar files are of the same version.

When i kept all the jars of same version, my issue got resolved. I hope this will help you .

Comments

1

You need to add @Valid in register method

@RequestMapping(value = "/register") public ModelAndView register(@Valid @ModelAttribute("user") UserBean user, BindingResult result) {

Comments

1

If you are using hibernate-validator, use version-6.2.4 Version 7 might not work.

Comments

0

In my case hibernate-validator jars are not available in run time. I've copied them to .../WEB-INF/lib/ then it worked correctly.

Comments

0

I added the usual stuff you have done (libraries in pom, @Valid on RequestBody etc)

<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.1.3.Final</version>
        </dependency>
        <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>3.0.1-b11</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

What the Spring docs (and many blogs) leave it as subtle is that Spring looks for an exit point to throw the error but if that exit doesn't exist, it will reply with 404. After reading a lot especially this blog, adding this class got Spring to recognize @Valid and find an exit point to throw the error

    @RestControllerAdvice
    @Order(1) 
    public class RestControllerExceptionHandler {

    @RequestMapping(value = { "error/404" }, method = RequestMethod.GET)
    @ExceptionHandler(Exception.class)
    public String handleUnexpectedException(Exception e) {
        return "views/base/rest-error";         
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String handlemethodArgumentNotValid(MethodArgumentNotValidException exception) { //
        // TODO you can choose to return your custom object here, which will then get transformed to json/xml etc.
        return "Sorry, that was not quite right: " + exception.getMessage();
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ConstraintViolationException.class)
    public String handleConstraintViolation(ConstraintViolationException exception) { //
        // TODO you can choose to return your custom object here, which will then get transformed to json/xml etc.
        return "Sorry, that was not quite right: " + exception.getMessage();
    }

    
}

Comments

0

i spent nearly 2 days fixing the same problem and ultimately found one solution, if you still have this problem, i would like to suggest you one answer, in my case, i tried using hibernate-validator-5.1.3.Final-dist.zip,5.2.4.Final-dist.zip, 7.0.0.Final-dist.zip but none of these worked for me but when i used *hibernate-validator-6.2.0.Final-dist*, it supports jarkarta validation but it works perfectly even though people say because of Jakarta Bean Validation it does not work in hibernate-validator's version post 5. it worked miraculously and believe me, it might work for you as well.

Comments

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.