Restrict annotation @Notnull and @Size cannot take effect in Spring Bean

Viewed 3817

I want to use annotation to check bean's property, but @NotNull and @Size annotation don't take effect. please see my code below:

Spitter bean:

package spittr.data;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Spitter {

    private int id;

    @NotNull
    @Size(min=5, max=25)
    private String password;

    @NotNull
    @Size(min=2, max=30)
    private String firstName;

    @NotNull
    @Size(min=2, max=30)
    private String lastName;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    } 

    public String toString()
    {
        return "id:" + id + "\n" +
               "firstName:" + firstName + "\n"+
               "lastName:" +lastName+"\n"+
               "password:" + password;
    }
}

SpitterController:

package spittr.web;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import spittr.data.Spitter;
import spittr.data.SpitterRespository;

@Controller
@RequestMapping("/spitter")
public class SpitterController {

    private SpitterRespository spitterRespository;
    public SpitterRespository getSpitterRespository() {
        return spitterRespository;
    }

    @Autowired
    public void setSpitterRespository(SpitterRespository spitterRespository) {
        this.spitterRespository = spitterRespository;
    }

    @RequestMapping(value="/register", method=RequestMethod.GET)
    public String showRegistrationForm(Model model)
    {
        model.addAttribute("spitter",new Spitter());
        System.out.println("SpitterController.showRegistrationForm is called");
        return "registForm";
    }

    @RequestMapping(value="/register", method=RequestMethod.POST)
    public String processRegistration(@Valid Spitter spitter, Errors errors)
    {
        if (errors.hasErrors())
        {

            return "registForm";
        }
        System.out.println("SpitterController.processRegistration is called");
        System.out.println(spitter.toString());
        spitterRespository.saveSpitter(spitter);

        return "redirect:/spitter/"+spitter.getId();
    }

    @RequestMapping(value="/{userId}", method=RequestMethod.GET)
    public String showSpitterProfile(@PathVariable("userId") String userId, Model model)
    {
        System.out.println("SpitterController.showSpitterProfile is called");
        Spitter spitter = spitterRespository.findSpitterById(userId);
        model.addAttribute("Spitter",spitter);
        return "userprofile";
    }
}

registForm.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form"  %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h1>Register</h1>
<sf:form method="POST" modelAttribute="spitter">
User ID: <sf:input  path="id" /><sf:errors path="id" />   <br />
First Name: <sf:input  path="firstName" /><sf:errors path="firstName" />  <br/>
Last Name: <sf:input  path="lastName" /><sf:errors path="lastName" /> <br/>
Password: <sf:input  path="password" /><sf:errors path="password" /> <br/>

<input type="submit" value="Register" />
</sf:form>
</body>
</html>

the effect that I click on Register button:

enter image description here

If I type some number in the ID field and keep the others as empty, the validation will be passed, but I think I have set @NotNull and @Size annotation on the Spitter bean, so it's not reasonable for spring to verify it successfully and jump to another page. but in fact, it does, what's wrong with my code?

3 Answers

I think that you need to use @Validated annotation, instead of @Valid in this line:

@RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegistration(@RequestBody @Validated Spitter spitter, Errors errors)

Try this it should resolve the issue :

@RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegistration(@RequestBody @Valid Spitter spitter, Errors errors)

Update from comment

by-default the content-type is application/json and you are sending contentType="text/html" which is incompatible. That's why you are getting HTTP 415 error "Unsupported Media Type".

You can explicitly define the content-type at controller lever like below :

@RequestMapping(value="/register", method=RequestMethod.POST, consumes="text/html", produces="text/html")

Try this one:

@RequestMapping(value="/register", method=RequestMethod.POST)
    public String processRegistration(@Valid @ModelAttribute("spitter") Spitter spitter,BindingResult bindingResult)
    {
        if (bindingResult.hasErrors())
        {

            return "registForm";
        }
        //rest of the code
    }
Related