0

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>
2
  • I see you're submitting a form. Do you have a POST method for your index? Commented Jul 20, 2016 at 6:13
  • The problem is not submitting the form but to display them using Spring modelAttribute. Commented Jul 20, 2016 at 10:03

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

1 Comment

THANK YOU!!!!!... page scoped variable and request attribute.... got it... thank you
0

You use <c:forEach var="result" items="${books}" varStatus="status"> and ${result.id} . you check in controller, by any chance? your books.

5 Comments

how is this different than what I have? If i get rid of modelAttribute i can display value by using JSTL but I am trying not to type ${book.id}, ${book.name}, ${book.price}...etc I am trying to use modelAttribute to get the model.... thank you
your code. List<Book> books = bookDao.getBookList(); check debug. take list?
why you don`t check object? you error : BindingResult.
List<Book> books contains list of books
I don`t know sf:form in model Attribute. why use sf:form in model Attribute? its works..... I've done my best.. bye.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.