khateeb
khateeb

Reputation: 5469

Spring MVC form validation not working

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>

Upvotes: 6

Views: 31037

Answers (10)

Manas
Manas

Reputation: 11

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

Upvotes: 1

hema
hema

Reputation: 11

You need to add @Valid in register method

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

Upvotes: 1

Rabindra Dahal
Rabindra Dahal

Reputation: 1

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.

Upvotes: 0

veritas
veritas

Reputation: 432

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();
    }

    
}

Upvotes: 0

Hari Krishna
Hari Krishna

Reputation: 3568

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

<mvc:annotation-driven />

Upvotes: 2

Siva R
Siva R

Reputation: 447

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

Upvotes: 0

Mitesh Upadhyay
Mitesh Upadhyay

Reputation: 11

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 .

Upvotes: 1

Witold Kaczurba
Witold Kaczurba

Reputation: 10515

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.

Upvotes: 5

Fathi
Fathi

Reputation: 11

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.

Upvotes: 1

Mannekenpix
Mannekenpix

Reputation: 752

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!

Upvotes: 11

Related Questions