t3rmin41
t3rmin41

Reputation: 678

Neither BindingResult nor plain target object for bean available as request attribute

I am trying to make simple CRUD web application using Java, Spring, Hibernate and MySQL. The problem where I'm stuck is that I cannot display form to add new item (pizza) to database.

Here is my controller:

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.support.SessionStatus;

@Controller
public class PizzaController {

  @Autowired private PizzaDao pizzaDao;

  @RequestMapping(method=RequestMethod.GET, value="/")
  public String indexPage(Model model) {
    List<Pizza> pizzas = pizzaDao.getAll();
    model.addAttribute("pizzas", pizzas);
    return "index";
  }
  @RequestMapping(method=RequestMethod.GET, value="Pizza/pizzalist")
  public String pizzalist(Model model) {
    List<Pizza> pizzas = pizzaDao.getAll();
    model.addAttribute("pizzas", pizzas);
    return "pizzalist/pizzalist";
  }
  @RequestMapping(method=RequestMethod.POST, value="Pizza/pizzalist/add")
  public String add(@ModelAttribute("mypizza") Pizza pizza) { //, BindingResult result,         SessionStatus status, ModelMap mmap) {
    //mmap.addAttribute("pizza",pizza);
    pizzaDao.add(pizza);
    //status.setComplete();
    return "pizzalist/pizzalist";
  }
  @RequestMapping(method=RequestMethod.GET, value="Pizza/pizzalist/delete")
  public String delete(@RequestParam("id")long id, Model model) {
    pizzaDao.delete(id);
    List<Pizza> pizzas = pizzaDao.getAll();
    model.addAttribute("pizzas", pizzas);
    return "pizzalist/pizzalist";
  }
  @RequestMapping(method=RequestMethod.POST, value="Pizza/edit")
  public String edit(Model model) {
    List<Pizza> pizzas = pizzaDao.getAll();
    model.addAttribute("pizzas", pizzas);
    return "pizzalist/pizzalist";
  }
}

And view:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ include file="/WEB-INF/jsp/includes.jsp"%>
<!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>Available pizzas</title>
</head>
<body>
    <h1>List of All Pizzas</h1>
    <table border="1">
        <c:forEach var="p" items="${pizzas}">
            <tr>
                <td>${p.name}</td><td>${p.price}</td><td><a href="pizzalist/delete?id=${p.id}">Delete</a></td>
            </tr>
        </c:forEach>
    </table>
    <br />
    <h1>Add new pizza</h1>
    <form:form modelAttribute="mypizza" method="POST" action="pizzalist/add">
    <table>
        <tr>
            <td>Name</td>
            <td><form:input path="name" /></td>
        </tr>
        <tr>
            <td>Price</td>
            <td><form:input path="price" /></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" name="action" value="Add" />
            </td>
        </tr>
    </table>
    </form:form>
    <br />
    <a href="/pizzashop">Go back to home page</a>
</body>
</html>

When I leave only table displaying available pizzas with links "Delete", everything is displayed OK and deleting also works OK.

I guess something is wrong with form and controller @ModelAttribute but I can't find what is exactly wrong, I am adding same attribute in controller as in form - "mypizza" and this should work (at least from what I was able to find on Google).

Can someone enlighten what prevents this application from working and how to solve the issue? If other config files are needed I can provide them.

UPD:

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'mypizza' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:179)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:199)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:165)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:152)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:143)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:127)
org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:421)
org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:142)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:103)
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80)
org.apache.jsp.WEB_002dINF.jsp.pizzalist.pizzalist_jsp._jspx_meth_form_005finput_005f0(pizzalist_jsp.java:243)
org.apache.jsp.WEB_002dINF.jsp.pizzalist.pizzalist_jsp._jspx_meth_form_005fform_005f0(pizzalist_jsp.java:194)
org.apache.jsp.WEB_002dINF.jsp.pizzalist.pizzalist_jsp._jspService(pizzalist_jsp.java:103)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
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:238)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:263)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

Upvotes: 2

Views: 50723

Answers (6)

tinku
tinku

Reputation: 341

If you have defined modelAttribute with form in your JSP then before reloading the JSP, spring will check for that modelAttribute and throw this type of exception if it is not available.

In this case, you have to set this modelAttribute in your controller first to prevent such type of exception.

model.addAttribute("myModelAttribute", new MyModelAttribute());

Upvotes: 0

you want to change this function:-value="Pizza/pizzalist"

@RequestMapping(method=RequestMethod.GET, value="Pizza/pizzalist")
public String pizzalist(@ModelAttribute("mypizza") Pizza pizza, Model model) {
List<Pizza> pizzas = pizzaDao.getAll();
model.addAttribute("pizzas", pizzas);
return "pizzalist/pizzalist";

this will help you.

Upvotes: 1

Vins
Vins

Reputation: 2070

I just want to add my 2 cents here. While copying from another page, some of my buttons went outside the end of </form> tag. I had the modelattribute and all related things. One of my <form:button> was outside the <form:form>.... </form:form> tags. It was crazy...

Just putting this answer as it may help someone else.

Upvotes: 1

Abhishek Nayak
Abhishek Nayak

Reputation: 3748

if the modelAttribute of <form:form is not available while the form is rendering. then the exception will raise, in your case mypizza is not available, The exception says the same:

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

you can add model bean/form backing object in any way you like:

using @ModelAttribute("mypizza") :

@ModelAttribute("mypizza")
public Pizza loadEmptyModelBean(){
   return new Pizza();
}

In your case @ModelAttribute("mypizza") option is perfect, instead of adding in every method add it in one place.


or in GET method (where @Shay Elkayam answer says the same):

@RequestMapping(method=RequestMethod.GET, value="/")
  public String indexPage(Model model) {
    List<Pizza> pizzas = pizzaDao.getAll();
    model.addAttribute("pizzas", pizzas);
    model.addAttribute("mypizza", new Pizza());// model bean added to use in form
    return "index";
  }

if you not do either, then Neither BindingResult nor plain target object for bean name 'mypizza' available exception will raise.

Upvotes: 6

t3rmin41
t3rmin41

Reputation: 678

To anyone who may encounter the problem:

I needed to add

@ModelAttribute("mypizza") 

to "pizzalist" method which now looks like this:

@RequestMapping(method=RequestMethod.GET, value="Pizza/pizzalist")
public String pizzalist(@ModelAttribute("mypizza") Pizza pizza, Model model) {
   List<Pizza> pizzas = pizzaDao.getAll();
   model.addAttribute("pizzas", pizzas);
   model.addAttribute("mypizza", new Pizza());
   return "pizzalist/pizzalist";
}

Also, needed to add Shay Elkayam suggested line to same method (I added just before "return" in "pizzalist" method) and to method "add" right at the start, which now looks like

@RequestMapping(method=RequestMethod.POST, value="Pizza/pizzalist/add")
public String add(@ModelAttribute("mypizza") Pizza pizza, Model model) {
    model.addAttribute("mypizza", new Pizza());
    pizzaDao.add(pizza);
    List<Pizza> pizzas = pizzaDao.getAll();
    model.addAttribute("pizzas", pizzas);
    return "pizzalist/pizzalist";
}

And now viewing of table and adding new item works OK. If anything, my WEB-INF folder structure is:

- jsp
   index.jsp
   - pizzalist
       pizzalist.jsp

Thanks to everyone who tried to help and show the correct way.

Upvotes: 5

Shay Elkayam
Shay Elkayam

Reputation: 4158

On this method:

@RequestMapping(method=RequestMethod.GET, value="/")
  public String indexPage(Model model) {
    List<Pizza> pizzas = pizzaDao.getAll();
    model.addAttribute("pizzas", pizzas);
    return "index";
  }

you should add the following line:

model.addAttribute("mypizza", new Pizza());

The form:form needs an "empty" model that corresponds to the modelAttribute you defined.

Upvotes: 8

Related Questions