I am trying to make a Book Management project where I have three buttons on the home.jsp page. Each button redirects to a separate page and each of these pages has a form. I have one Controller class that has three methods to handle each form submissions from each of these pages but when I try to use @ModelAttribute in the JSP page for any form, I am unable to get the value that I add to the Model.
Here is the home.jsp:
<body> <div class="container"> <div> <h1>Spring Boot Web JSP Example</h1> <h2>Name: ${book.name}</h2> <h2>Author: ${book.author}</h2> <h2>ISBN: ${book.isbn}</h2> </div> </div> <form:form method="POST" action="/get" modelAttribute="newBook"> <div class="form-group"> <label for="authorInput">Author</label> <form:input path="author" cssClass="form-control" id="authorInput"></form:input> </div> <div class="form-group"> <label for="dateInput">Date</label> <form:input path="date" cssClass="form-control" id="dateInput"></form:input> </div> <button type="submit" class="btn btn-primary">Get Book</button> </form:form> <a href="../add.jsp"><button type="submit" class="btn btn-primary">Add Book</button></a> <a href="../update.jsp"><button type="submit" class="btn btn-primary">Update Book</button></a> </body>
Here is the controller class:
@Controller public class MainController {
@GetMapping(value = "/") public String welcome(Map<String, Object> model) { model.put("newBook", new Book()); model.put("updateBook", new Book()); model.put("addBook",new Book()); return "home"; } @PostMapping(value = "/get") public String change(@RequestParam("author") String author, Model model, @ModelAttribute("newBook")Book book) { System.out.println(author); Book b = BookDao.getBook(book.getAuthor(), book.getDate()); if(b == null){ return "home"; } model.addAttribute("book", b); model.addAttribute("newBook", new Book()); return "home"; } @RequestMapping(value = "/add") public String addBook(@RequestParam("author") String author, @RequestParam("isbn") int isbn, Model model, @ModelAttribute("addBook") Book book){ System.out.println("Author: "+author + " ISBN: "+isbn); model.addAttribute("addBook", new Book()); Book b= new Book(book.getName(), author,isbn, book.getDate()); model.addAttribute("add", book); boolean result = BookDao.addBook(b); if(result) return "home"; else return "error"; } @RequestMapping( value = "/update") public String updateBook(@RequestParam("author") String author, @RequestParam("isbn") int isbn, Model model, @ModelAttribute("updateBook") Book book){ System.out.println("Author: "+author + " ISBN: "+isbn); Book b= new Book(book.getName(), author,isbn, book.getDate()); model.addAttribute("updateBook", new Book()); model.addAttribute("update",b); BookDao.updateBook(isbn, b); return "home"; }
}
And here are the other two jsp pages: Add.jsp:
<body> <h1>Add a Book</h1> <form:form method="POST" action="/add" modelAttribute="addBook"> <div class="form-group"> <label for="nameInput">Name</label> <form:input path="name" cssClass="form-control" id="nameInput"></form:input> </div> <div class="form-group"> <label for="authorInput">Author</label> <form:input path="author" cssClass="form-control" id="authorInput"></form:input> </div> <div class="form-group"> <label for="isbnInput">ISBN</label> <form:input path="isbn" cssClass="form-control" id="isbnInput"></form:input> </div> <div class="form-group"> <label for="dateInput">Date</label> <form:input path="date" cssClass="form-control" id="dateInput"></form:input> </div> <button type="submit" class="btn btn-primary">Add</button> </form:form> </body>
Update Book JSP Page:
<body> <form:form method="POST" action="/update" modelAttribute="third"> <div class="form-group"> <label for="authorInput">ISBN</label> <form:input path="isbn" cssClass="form-control" id="authorInput"></form:input> </div> <div class="form-group"> <label for="nameInput">Name</label> <form:input path="name" cssClass="form-control" id="nameInput"></form:input> </div> <div class="form-group"> <label for="authorInput">Author</label> <form:input path="author" cssClass="form-control" id="authorInput"></form:input> </div> <div class="form-group"> <label for="dateInput">Date</label> <form:input path="date" cssClass="form-control" id="dateInput"></form:input> </div> <button type="submit" class="btn btn-primary">Update Book</button> </form:form> </body>
The problem is that the lines modelAttribute=”addBook” and modelAttribute=”third” in the add.jsp page and update.jsp page throw an error. The IDE says “Cannot resolve symbol ‘addBook/third'”. Those values are available in the home.jsp page though.
Advertisement
Answer
Since I found the answer, I will post it just in case somebody else gets stuck with it. In order to access the forms on another JSP page, we can’t just directly redirect to the page in an MVC design. In order to do so, we need to create a @GetMapping annotation method for each of those JSP forms @PostMapping annotations and then redirect to the @GetMapping methods first and the @GetMapping will redirect to the JSP page. This is how it should be done:
Controller Class:
@Controller public class MainController {
@GetMapping(value = "/") public String welcome(Map<String, Object> model) { model.put("newBook", new Book()); return "home"; } @PostMapping(value = "/get") public String change(@RequestParam("author") String author, Model model, @ModelAttribute("newBook")Book book) { System.out.println(author); Book b = BookDao.getBook(book.getAuthor(), book.getDate()); if(b == null){ return "home"; } model.addAttribute("book", b); model.addAttribute("newBook", new Book()); return "home"; } @GetMapping("/add") public String show(Model model) { model.addAttribute("addBook", new Book()); return "add"; } @PostMapping(value = "/add") public String addBook(@RequestParam("author") String author, @RequestParam("isbn") int isbn, Model model, @ModelAttribute("addBook") Book book){ System.out.println("Author: "+author + " ISBN: "+isbn); model.addAttribute("addBook", new Book()); Book b= new Book(book.getName(), author,isbn, book.getDate()); model.addAttribute("add", book); boolean result = BookDao.addBook(b); if(result) return "home"; else return "error"; } @GetMapping("/update") public String showUpdate(Model model) { model.addAttribute("updateBook", new Book()); return "update"; } @PostMapping( value = "/update") public String updateBook(@RequestParam("author") String author, @RequestParam("isbn") int isbn, Model model, @ModelAttribute("updateBook") Book book){ System.out.println("Author: "+author + " ISBN: "+isbn); Book b= new Book(book.getName(), author,isbn, book.getDate()); model.addAttribute("updateBook", new Book()); model.addAttribute("update",b); BookDao.updateBook(isbn, b); return "home"; }
And the JSP page for Home.jsp page should be as follows:
<form:form method="POST" action="/get" modelAttribute="newBook"> <div class="form-group"> <label for="authorInput">Author</label> <form:input path="author" cssClass="form-control" id="authorInput"></form:input> </div> <div class="form-group"> <label for="dateInput">Date</label> <form:input path="date" cssClass="form-control" id="dateInput"></form:input> </div> <button type="submit" class="btn btn-primary">Get Book</button> </form:form> <a href ="/add"><button type="submit" class="btn btn-primary">Add Book</button></a> <a href ="/update"><button type="submit" class="btn btn-primary">Update Book</button></a> </body>
So the href maps to the @GetMapping method to get the ModelAttributes. The other JSP pages are fine as it is.
Also, another good practice I might suggest is to Use a Service layer/package to perform all the operations. So instead of performing it in the Controller, we delegate tasks like the CRUD operations to the Service layer which in turn interacts with the DAO layer.