Fenzox
Fenzox

Reputation: 354

SpringMVC - Java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name

I'm new to Spring MVC and is making a simple todo web app. I'm getting the following error while binding data. I believe there is something with the jsp file with the Springmvc form where it messed up the binding process. I assume the bindingresult will return the form again but it does not for some reason.

org.apache.jasper.JasperException: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'todo' available as request attribute
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:549)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:465)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1257)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

My updateToDo.jsp form

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>update task</title>
<link href="webjars/bootstrap/4.5.0/css/bootstrap.min.css"
    rel="stylesheet">

</head>
<body>
    <div class="container">
        <H1>update your task!</H1>
    
        <form:form method="POST" commandName="todo">
            
            <fieldset class="form-group">
                <form:label path="description">Description:</form:label>
                <!-- required validates nulll -->
                <form:input path="description" type="text" class="form-control"
                    required="required" />
                <form:errors path="description" cssClass="text-warning" />
            </fieldset>

            <fieldset class="form-group">
                <form:label path="targetDate">Target Date</form:label>
                <form:input path="targetDate" type="Date" class="form-control"
                    required="required" />
                <form:errors path="targetDate" cssClass="text-warning" />

            </fieldset>
            <fieldset class="form-group">
                <form:radiobutton path="completion" value="true" />
                <form:radiobutton path="completion" value="false" />
                <form:errors path="targetDate" cssClass="text-warning" />
            </fieldset>

            <button type="submit" class="btn btn-success">Submit Update</button>
        </form:form>
        
    </div>
    <script src="webjars/jquery/3.5.1/jquery.min.js"></script>
    <script src="webjars/bootstrap/4.5.0/js/bootstrap.min.js"></script>

</body>
</html>

Controller

@Controller
public class ToDoController {

@Autowired
private ToDoService service;

@InitBinder
protected void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("mm/DD/yyyy");
    binder.registerCustomEditor(Date.class, new CustomDateEditor(
            dateFormat, false));
}

@RequestMapping(value = "/list-todo", method= RequestMethod.GET)
// HttpSession allows access to the session
public String showToDo(ModelMap model,  HttpSession httpSession) {
    String user = (String) httpSession.getAttribute("name");
    model.addAttribute("todos", service.retrieveTodos(user));
    return "list-todos";
}

// redirect to update form
@RequestMapping(value = "/update-todo", method= RequestMethod.GET)
public String getUpdateForm(ModelMap model, @RequestParam int id) {
    // To work with command bean
    model.addAttribute("todo", service.retrieveTodo(id));
    model.clear();
    return "updateToDo";
}

@RequestMapping(value = "/update-todo", method= RequestMethod.POST)
public String submitUpdate(ModelMap model, @Valid ToDo todo, BindingResult result) {
    if (result.hasErrors()) {
        return "redirect:/update-todo";
    }
    service.updateToDo(todo);
    model.clear();
    return "redirect:/list-todo";
}

// Will be executed first
@RequestMapping(value = "/add-todo", method= RequestMethod.GET)
public String showAddForm(ModelMap model) {
    model.addAttribute("todo", new ToDo());
    return "addToDo";
}


/*
 * Will be executed after form is submitted
 * @Valid ToDo - command bean from addToDo.jsp. 
 * @Valid to validate the information
 * @BindingResult showcases the result of the validation
 */
@RequestMapping(value = "/add-todo", method= RequestMethod.POST)
public String submitAddForm(ModelMap model , @Valid ToDo todo,  HttpSession httpSession, BindingResult result) {
    System.out.println("running" + result);
    // If there is validation error , return to addToDos page for user to fix the error
    if (result.hasErrors()) {
        return "redirect:/showAddForm";
    }
    String user = (String) httpSession.getAttribute("name");
    service.addTodo(user, todo.getDescription(), todo.getTargetDate(), false);      
    // Clears the url e.g. name?=jyj123
    model.clear();
    // return to the url which executes the showToDO
    return "redirect:/list-todo";
}

    // delete to do entry
 @RequestMapping(value = "/delete-todo", method= RequestMethod.GET) 
 public String deleteToDo(ModelMap model, @RequestParam int id) { 
     service.deleteTodo(id);
     model.clear();
     return "redirect:/list-todo"; }

}

Upvotes: 0

Views: 128

Answers (2)

Minar Mahmud
Minar Mahmud

Reputation: 2665

In layman's terms this is how Spring MVC works -

  • Create a bean (generally in GET handler) to which you want to bind your data. (This bean is referred to as command object)

  • Put the command object in model

  • Return a view name. (Spring will resolve the view and send the model to the view)

  • Bind data (user input) to the command object

  • Retrieve the command object with data in the controller (POST or other alike handlers)


Solution to Your Problem:

You are calling model.clear(); in your GET handler. So, in the view layer, the model is empty and no target bean (i.e. command object) is available to bind data to.

So remove the mode.clear(); call.

NOTE

One other common mistake is to use different names for the key of the command object in the model and in the value of commandName of <form:form/>.

i.e., If you put the command object in model as model.put("fooBar", someFooBar);, in view you need to do <form:form commandName="fooBar" .../>


Further Reading

Upvotes: 0

You are calling model.clear(), so removed todo attribute.

    public String getUpdateForm(final ModelMap model, @RequestParam final int id) {
        // To work with command bean
        model.addAttribute("todo", service.retrieveTodo(id));
        model.clear();
        return "updateToDo";
    }

Upvotes: 1

Related Questions