Neither BindingResult nor plain target object for

2019-08-08 15:24发布

问题:

I have a problem when trying to access the controller.

Here is my controller:

@Controller
@RequestMapping("/index.htm")
public class LoginController {

    @Autowired
    private UserService userService;

    @RequestMapping(method = RequestMethod.GET)
    public String showForm(Map model) {
        model.put("index", new LoginForm());
        return "index";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processForm(LoginForm loginForm, BindingResult result,
                              Map model) {

        if (result.hasErrors()) {
            HashMap<String, String> errors = new HashMap<String, String>();
            for (FieldError error : result.getFieldErrors()) {
                errors.put(error.getField(), error.getDefaultMessage());
            }
            model.put("errors", errors);
            return "index";
        }

        List<User> users = userService.getUsers();
        loginForm = (LoginForm) model.get("loginForm");

        for (User user : users) {
            if (!loginForm.getEmail().equals(user.getEmail()) || !loginForm.getPassword().equals(user.getPassword())) {
                return "index";
            }
        }

        model.put("index", loginForm);
        return "loginsuccess";
    }

}

Here is my form:

    <form:form action="index.htm" commandName="index">

        <table border="0" cellspacing="12">
            <tr>
                 <td>
                     <spring:message code="application.loginForm.email"/>
                 </td>
                 <td>
                    <form:input path="email"/>
                 </td>
                 <td class="error">
                    <form:errors path="email"/>
                 </td>
            </tr>
            <tr>
                 <td>
                     <spring:message code="application.loginForm.password"/>
                 </td>
                 <td>
                    <form:password path="password"/>
                 </td>
                 <td class="error">
                    <form:errors path="password"/>
                 </td>
            </tr>
            <tr>
                 <td>
                     <input type="submit" value="Submit"/>
                 </td>
            </tr>
        </table>

    </form:form>

On form submit I am getting this exception:

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'index' available as request attribute.

What am I doing wrong here?

回答1:

It's because you're only doing this bit down at the bottom

model.put("index", loginForm);

If you return from the validation error, or from a success, there is no backing object in the model map named "index" so your form tag that has commandName="index" pitches a fit.

A common solution is to simply do this

@ModelAttribute("index")
public LoginForm getLoginForm() {
  return new LoginForm();
}

Then there will always be one present, and you can take adding it out of the GET method.