Java EE Servlet tutorial : Adding create, update and delete to the bookstore listing
From Resin 4.0 Wiki
(Created page with "==Java EE Servlet Tutorial: Implementing a basic CRUD listing== We left off with a basic listing. <code>BookListServlet</code> used a <code>BookRepository</code> object (DAO...") |
|||
Line 49: | Line 49: | ||
The link <code>/bookstore/book/</code> (with slash) loads the book listing. The link <code>/bookstore/book?id=1</code> loads | The link <code>/bookstore/book/</code> (with slash) loads the book listing. The link <code>/bookstore/book?id=1</code> loads | ||
the form page to edit an existing book. To add a new book, we will use the link <code>/bookstore/book</code>. | the form page to edit an existing book. To add a new book, we will use the link <code>/bookstore/book</code>. | ||
+ | |||
+ | == Adding a link to the book listing to add a book == | ||
====Adding an add book link to book-list.jsp listing==== | ====Adding an add book link to book-list.jsp listing==== | ||
Line 61: | Line 63: | ||
Now we have to links going to the URI /book, we need a Servlet that handles the links. | Now we have to links going to the URI /book, we need a Servlet that handles the links. | ||
The <code>BookEditorServlet</code> handles both add and the edit book functions. | The <code>BookEditorServlet</code> handles both add and the edit book functions. | ||
+ | |||
+ | == Servlet doGet to load a Book form == | ||
+ | |||
==== BookEditorServlet.java doGet ==== | ==== BookEditorServlet.java doGet ==== | ||
Line 127: | Line 132: | ||
</pre> | </pre> | ||
+ | |||
+ | == Rendering the book form HTML == | ||
Line 231: | Line 238: | ||
The <code>doPost</code> method of <code>BookEditorServlet</code> handles the form submission as follows: | The <code>doPost</code> method of <code>BookEditorServlet</code> handles the form submission as follows: | ||
+ | |||
+ | == Creating a doPost method to handle the form submission == | ||
==== BookEditorServlet.java doPost ==== | ==== BookEditorServlet.java doPost ==== |
Revision as of 00:00, 1 May 2012
Contents |
Java EE Servlet Tutorial: Implementing a basic CRUD listing
We left off with a basic listing. BookListServlet
used a BookRepository
object (DAO) to load a list of books and then delegated to book-list.jsp
to render
the book listing.
In this step, we want to add a link to the book listing so when the user clicks it a form gets rendered so that they can edit the details of book. Also we want an add link so that the end user can add a new book to the listing.
Adding a link to the book listing to edit a book
Change the code that looks like this in book-list.jsp:
... <c:forEach var="book" items="${books}"> <tr> <td>${book.title}</td> ...
To this
Adding an edit book link to book-list.jsp listing
... <c:forEach var="book" items="${books}"> <tr> <td><a href="${pageContext.request.contextPath}/book?id=${book.id}">${book.title}</a></td> ...
The EL expression ${pageContext.request.contextPath}
refers to the URI you have the war file mapped to in the
Servlet container. The default URI for a webapp is its war file name so our war file name is bookstore so a rendered
URL will look like this:
... <tr> <td><a href="/bookstore/book?id=0">War and Peace</a></td> ... <tr> <td><a href="/bookstore/book?id=1">Pride and Prejudice</a></td> ...
The link /bookstore/book/
(with slash) loads the book listing. The link /bookstore/book?id=1
loads
the form page to edit an existing book. To add a new book, we will use the link /bookstore/book
.
Adding a link to the book listing to add a book
Adding an add book link to book-list.jsp listing
Before the table add this HTML code to add a new book:
... <a href="${pageContext.request.contextPath}/book">Add Book</a> ...
Now we have to links going to the URI /book, we need a Servlet that handles the links.
The BookEditorServlet
handles both add and the edit book functions.
Servlet doGet to load a Book form
BookEditorServlet.java doGet
package com.bookstore.web; ... @WebServlet("/book") public class BookEditorServlet extends HttpServlet { @Inject private BookRepository bookRepo; private SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy"); ... /** Prepare the book form before we display it. */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getParameter("id"); if (id != null && !id.isEmpty()) { Book book = bookRepo.lookupBookById(id); request.setAttribute("book", book); request.setAttribute("bookPubDate", dateFormat.format(book.getPubDate())); } /* Redirect to book-form. */ getServletContext().getRequestDispatcher("/WEB-INF/pages/book-form.jsp").forward( request, response); } }
Notice we use @WebServlet("/book")
to map BookEditorServlet
to the URI /book.
It is common to load a form from a doGet
method, and to handle the form submission via doPost
.
Following REST and HTTP principles GET operations reads data, and POST data modifies data.
The doGet
method uses the id being empty or not to determine if this is a load
"Add Employee Form" or load "Update Employee Form" operation. The doGet method also converts
the date into a format that is easy for the end user to modify and it also maps the book into request scope as follows:
BookEditorServlet.java doGet() delegate to book-form.jsp page
Book book = bookRepo.lookupBookById(id); request.setAttribute("book", book); request.setAttribute("bookPubDate", dateFormat.format(book.getPubDate()));
In the model 2 architecture, the Servlet tier prepares the form data before a form loads to be rendered and edited correctly.
To render the HTML form, the servlet delegates to book-form.jsp as follows:
BookEditorServlet.java doGet() delegate to book-form.jsp page
/* Redirect to book-form. */ getServletContext().getRequestDispatcher("/WEB-INF/pages/book-form.jsp").forward( request, response);
Rendering the book form HTML
The book-form.jsp has the HTML code to render a form as follows:
book-form.jsp Renders form to update or add a Book
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML> <html> <head> <title>Book Form</title> </head> <body> <h1>Book Form</h1> <form method="post" action="${pageContext.request.contextPath}/book"> <fieldset> <legend> <c:choose> <c:when test="${not empty book.id }"> Updating Book </c:when> <c:otherwise> Adding Book </c:otherwise> </c:choose> </legend> <div> <label for="title">Title</label> <input type="text" name="title" id="title" value="${book.title}" /> </div> <div> <label for="description">Description</label> <textarea name="description" id="description" rows="2" cols="60">${book.description}</textarea> </div> <div> <label for="price">Price $</label> <input name="price" id="price" value="${book.price}" /> </div> <div> <label for="pubDate">Publication Date</label> <input name="pubDate" id="pubDate" value="${bookPubDate}" /> <label class="after">(MM/DD/YYYY)</label> </div> <c:if test="${not empty book.id}"> <input type="hidden" name="id" value="${book.id}" /> </c:if> </fieldset> <div class="button-row"> <a href="${pageContext.request.contextPath}/book/">Cancel</a> or <input type="submit" value="Submit" /> </div> </form> </body> </html>The
book-form.jspuses JSTL c:choose, c:otherwise to display whether we are adding a new book or updating a book as follows:
book-form.jsp using JSTL c:choose to display update or add status
... <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> ... <legend> <c:choose> <c:when test="${not empty book.id }"> Updating Book </c:when> <c:otherwise> Adding Book </c:otherwise> </c:choose> </legend> ...
If the book.id
property is present the test "Updating Book" is rendered.
Also, the form renders a hidden id property if it is doing an edit/update operation as follows:
<c:if test="${not empty book.id}"> <input type="hidden" name="id" value="${book.id}" /> </c:if>
The doPost
method of BookEditorServlet
handles the form submission as follows:
Creating a doPost method to handle the form submission
BookEditorServlet.java doPost
package com.bookstore.web; ... @WebServlet("/book") public class BookEditorServlet extends HttpServlet { @Inject private BookRepository bookRepo; ... /** * Handles posting an HTML book form. If the id is null then it is an * "add book", if the id is set then it is an "update book" */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String title = request.getParameter("title"); String description = request.getParameter("description"); String price = request.getParameter("price"); String pubDate = request.getParameter("pubDate"); String id = request.getParameter("id"); if (id == null || id.isEmpty()) { bookRepo.addBook(title, description, price, pubDate); } else { bookRepo.updateBook(id, title, description, price, pubDate); } response.sendRedirect(request.getContextPath() + "/book/"); } ... }
Notice that if the id is null then BookEditorServlet.doPost
calls bookRepo.addBook
, otherwise it calls bookRepo.updateBook
.
Once the form handling is done, doPost
redirects to /book/
. A redirect means an extra hit to the server, since we are basically
telling the browser to load another link. The astute reader may wonder why we don't just do a forward like we did in the doGet
.
The answer is bookmarking. The URL /book/
(ending in slash) represents a collection of books,
while /book (no slash) represents a single book (using REST style URL).
If we did a forward, then after the form submission the browser would show the listing, but under the URI /book instead of /book/.
If the ender user linked to /book, it would not take them back to the listing but back to a form, which not correct.
This is why we do a sendRedirect instead of a forward.
Now we have an add/edit/update/read/ and listing. It is everything you could want from a CRUD listing.
At this point, we don't do much validation. We will add this in a later lesson.