Reputation: 1264
I have a controller that goes to the DB and get a list of books. I like to use @modelAttribute to display individual books in separate form so I can do quick edits on each item.
Controller
@RequestMapping("/")
public String pagIndex(Model model){
System.out.println("loading index page");
// Get list of books
List<Book> books = bookDao.getBookList();
// List of object to Model
model.addAttribute("books", books);
return "index";
}
View
<h3>Book Inventory</h3>
<table>
<tr>
<td>ID</td>
<td>Book Name</td>
<td>ISPN</td>
<td>Price</td>
<td></br><td>
<td>Object</td>
</tr>
<!-- Each book in separate form for easy update -->
<c:forEach var="book" items="${books}">
<tr>
<sf:form class="editeForm" action="${pageContext.request.contextPath}/edititem" modelAttribute="book" method="POST">
<td>${book.id} <input type="hidden" path="id" name="id"></td>
<td><sf:input type="text" path="name" name="name" /></td>
<td><sf:input type="text" path="ispn" name="ispn" /></td>
<td><sf:input type="text" path="price" name="price" /></td>
<td></br><td>
<td>${book}</td>
<td><input type="submit" value="save edite"><input type="submit" name="delete" value="delete"></td>
</sf:form>
</tr>
</c:forEach>
</table>
When i set modelAttribute="book" stack trace is
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'book' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144)
modelAttribute="${book}" stack trace is
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'Book bean [id=1, name=Java: A Beginner's Guide, ispn=978-0071809252, price=18' available as request attribute
Update: If I use plain JSTL it works but anyway to use modelAttriburte?
<h3>Book Inventory</h3>
<table>
<tr>
<td>ID</td>
<td>Book Name</td>
<td>ISPN</td>
<td>Price</td>
<td></br><td>
<td>Object</td>
</tr>
<!-- Each book in separate form for easy update -->
<c:forEach var="book" items="${books}">
<tr>
<form class="editeForm" action="${pageContext.request.contextPath}/edititem" method="POST">
<td>${book.id} <input type="hidden" name="id" value="${book.id}"/></td>
<td><input type="text" name="name" value="${book.name} /></td>
<td><input type="text" name="ispn" value="${book.ispn} /></td>
<td><input type="text" name="price" value="${book.price} /></td>
<td></br><td>
<td>${book}</td>
<td><input type="submit" value="save edite"><input type="submit" name="delete" value="delete"></td>
</form>
</tr>
</c:forEach>
</table>
Upvotes: 0
Views: 2755
Reputation: 148965
When you write:
<c:forEach var="book" items="${books}">
the book
variable is indeed created for each iteration, but it is only a page scoped variable and not a request attribute. And as the error says, Spring modelAttribute is expected to be a request attribute. As I know no trivial way to dynamically make the book
variable be a true spring model attribute, my advice is to stick with plain JSTL.
As the JSTLView by default only puts the model attributes as request attributes with their name, you could use a little scriptlet to try to cheat spring:
<c:forEach var="book" items="${books}">
<%
Object obj = pageContext.findAttribute("book");
request.setAttribute("book", obj);
%>
...
But I really urge you not to do that, because it relies on Spring implementation details that can change even in a minor release
Upvotes: 1
Reputation: 1423
You use <c:forEach var="result" items="${books}" varStatus="status">
and ${result.id}
. you check in controller, by any chance? your books.
Upvotes: 0