Using JPA to build a J2EE 3-tier Web Application

The purpose of this entry is to demonstrate a full J2EE web application. The application will generate:

    1. a Java Persistence API (JPA) entity modeled on an existing database table
    2. an Enterprise JavaBean (EJB) which will query the database through the JPA
    3. a Servlet coupled with a JavaServer Faces (JSF) 2 framework for information display
    4. a Representational State Transfer (REST) resource capable of providing the JPA entities as web resources

The project will be built in Netbeans 7.2.1 and hosted on Glassfish 3.2.1

Start off by creating a Web Application project and specify the Glassfish Server. Then, clicking on the project, create a new Entity Class from Database (under Persistence) and specify the datasource along with the required tables. Specify a package. Check the NamedQuery, JAXB and Persistence Unit boxes.

Image

Next, create a new stateless EJB in the package (with the annotation @Stateless). We will be using JPA entities as RESTful resources, so tell netbeans to register all REST resources to the javax.ws.rs.Application class automatically and add a Jersey Library (JAX-RS implementation).

@javax.inject.Named
@Path("/customers")
@Stateless
public class CustomerSessionBean {

    @PersistenceContext
    EntityManager em;

    public List<Customer> getCustomers() {
        return (List<Customer>)em.createNamedQuery("Customer.findAll").getResultList();
    }

    //RESTful resource, access at http://localhost:8080/JavaEE6SampleApp/webresources/customers/customer/1
    @GET
    @Path("/customer/{id}")
    @Produces("application/xml")
    public Customer getCustomer(@PathParam("id")Integer id) {
        return
        (Customer)em.createNamedQuery("Customer.findByCustomerId")
        .setParameter("customerId", id).getSingleResult();
    }
}

Next, create the servlet that uses the EJB.

@WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet"})
public class TestServlet extends HttpServlet {

    @EJB CustomerSessionBean ejb;

    // Access at http://localhost:8080/JavaEE6SampleApp/TestServlet
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet TestServlet</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet TestServlet at " + request.getContextPath () + "</h1>");
            out.println(ejb.getCustomers());
            out.println("</body>");
            out.println("</html>");
        } finally {
            out.close();
        }
    }

    // HTTPServlet Methods go here
}

Next, we will go about creating the Context and Dependency Injection (CDI) which allows the EJB to support the JSF pages. Create a beans.xml file in the project and set the project framework to JSF. Create a Facelets Template (JSF) in the WEB-INF folder using one of the CSS layouts. Edit it to become:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link href="./../resources/css/default.css" rel="stylesheet" type="text/css" />
        <link href="./../resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
        <title>Facelets Template</title>
    </h:head>
    <h:body>
        <div id="top">
            <ui:insert name="top"><h1>Java EE 6 Sample App</h1></ui:insert>
        </div>

        <div id="content" class="center_content">
            <ui:insert name="content">Content</ui:insert>
        </div>

        <div id="bottom">
            <ui:insert name="bottom"><center>DEMO!</center></ui:insert>
        </div>
    </h:body>
</html>

Delete the old index.xhtml file and replace it with a new Facelets Template Client copy. In this case, the root tag used is :

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./WEB-INF/template.xhtml"
                xmlns:h="http://java.sun.com/jsf/html">
    <ui:define name="content">
        <h:dataTable value="#{customerSessionBean.customers}" var="c">
            <h:column>#{c.name}</h:column>
            <h:column>#{c.customerId}</h:column>
        </h:dataTable>
    </ui:define>
</ui:composition>

And we are done. The final results are:

Screenshot from 2013-01-07 12:34:30 Screenshot from 2013-01-07 12:34:43 Screenshot from 2013-01-07 12:34:53 Screenshot from 2013-01-07 12:35:17

Comet / WebSocket: web server/browser support

Sometimes it is hard to keep track of which web server and browser are supporting Comet and/or WebSocket. The following is from JFarcand, the developer of Grizzly and Atmosphere framework.

Web Server Support

(LP: long-Polling HS: Http Streaming)

Server Version Native Comet Native WebSocket WebSockets LP HS JSONP
Netty 3.3.x X X X X X X
Jetty 5.x X X X
Jetty 6.x X X X X
Jetty 7.x X X X X X X
Jetty 8.x X X X X X X
GlassFish 2.x X X X X
GlassFish 3.x to 3.1.1 X X X X
GlassFish 3.1.2 X X X X X X
Tomcat 5.x X X X
Tomcat 6.x X X X X
Tomcat 7.0.26 and lower X X X X
Tomcat 7.0.27 and up X X X X X X
JBoss 5.x X X X
JBoss 6.x X X X X
JBoss 7.x X X X X
WebLogic 10.x X X X X
WebLogic 11.x and up X X X X
Resin 2.x X X X
Resin 3.x X  X X X X
WebSphere 7.x X X X
WebSphere 8.x X X X

Browser Support

Browser Version WebSockets Long-Polling Http Streaming JSONP
Firefox 3.x to 8.x X X X
Firefox 9.x to 11.x X X X X
Chrome 12.x and lower X X X
Chrome 13.x and higher X X X X
Internet Explorer 6x to 9.x X X X
Internet Explorer 10.x X X X X
Opera 10.x and lower X X
Opera 11.x X X X
Safari 4.x X X X
Safari 5.x X X X X
Android 2.x and up X X X
Safari (iOS) 1.x to 4.x X X X
Safari (iOS) 5.x X X X X

Order Entry System 3: JSP, Servlet, Session Bean, JQuery

This is the final part of the series:

OrderSaveServlet.java

The OrderSaveServlet is the controller to save the CustomerBean from the session memory to a table “customer” in MySQL database via JNDI connection pool on GlassFish Application Server. It obtains the generated customer id from the database. Then, it saves the OrderBean and customer id into a another table “orders” in the database, and obtains the order id generated by the database insertion. It finally generates a html page to display the order number back to user. And our Order Entry Web System will end here.

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;
import mybean.CustomerBean;
import mybean.OrderBean;

@WebServlet(name = "OrderSaveServlet", urlPatterns = {"/OrderSaveServlet"})
public class OrderSaveServlet extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * &lt;code&gt;GET&lt;/code&gt; and
     * &lt;code&gt;POST&lt;/code&gt; methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            HttpSession session = request.getSession();
            CustomerBean CustomerBean = (CustomerBean)session.getAttribute("CustomerBean");

            InitialContext ctx = new InitialContext();
            DataSource ds = (DataSource)ctx.lookup("jdbc/MySQLPool");

            Connection conn = ds.getConnection();
            Statement stmt = conn.createStatement();

            String query1 = "INSERT INTO customer (name, address, tel, email) VALUES ( '" +
                    CustomerBean.getName() +"','"+
                    CustomerBean.getAddress()+"','"+
                    CustomerBean.getTel()+"','"+
                    CustomerBean.getEmail()+"') ";

            stmt.executeUpdate(query1);

            int customerid = -1;

//            ResultSet rs = stmt.getGeneratedKeys();
            ResultSet rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");

            if (rs.next()) {
                customerid = rs.getInt(1);
            } else {

                // throw an exception from here
            }

            OrderBean OrderBean = (OrderBean)session.getAttribute("OrderBean");

            String query2 = "INSERT INTO orders (itemid, saleprice, gst, qty, customerid) VALUES ( " +
                    OrderBean.getItemid() +","+
                    OrderBean.getSaleprice()+","+
                    OrderBean.getGst()+","+
                    OrderBean.getQty()+","+
                    customerid+") ";

            stmt.executeUpdate(query2);

            int orderid = -1;

//            ResultSet rs = stmt.getGeneratedKeys();
            rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");

            if (rs.next()) {
                orderid = rs.getInt(1);
            } else {

                // throw an exception from here
            }

            stmt.close();
            conn.close();

            out.println("&lt;html&gt;");
            out.println("&lt;head&gt;");
            out.println("&lt;title&gt;Servlet OrderSaveServlet&lt;/title&gt;");            
            out.println("&lt;/head&gt;");
            out.println("&lt;body&gt;");
//            out.println("&lt;p&gt;query: " + query2 + "&lt;/p&gt;");
            out.println("&lt;h1&gt;Thank you. Your Order Number: " + orderid + "&lt;/h1&gt;");
            out.println("&lt;/body&gt;");
            out.println("&lt;/html&gt;");
        } catch (Exception e) {
          //  e.printStackTrace();
        } finally {                        
            out.close();
        }
    }

    // &lt;editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."&gt;
    /**
     * Handles the HTTP
     * &lt;code&gt;GET&lt;/code&gt; method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * &lt;code&gt;POST&lt;/code&gt; method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// &lt;/editor-fold&gt;
}

Order Entry System 2: JSP, Servlet, Session Bean, JQuery

This is the second part of the series:

OrderEntry.jsp

This JSP  allows the user to entre the quantity, and calculates the gst and total payment by using the on-page JQuery function, and passed the control to OrderCustomer.jsp

<%--
    Document   : OrderEntry
    Created on : 14-Mar-2012, 12:57:23 AM
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<jsp:useBean id="rs" scope="request" type="java.sql.ResultSet" />
<jsp:useBean id="OrderBean" scope="session"/>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Order Entry</title>
       <style>
           body {
               font-family: sans-serif;
           }
           #summation {
               font-size: 18px;
               font-weight: bold;
               color:#174C68;
           }
           .txt {
               background-color: #FEFFB0;
               font-weight: bold;
               text-align: right;
           }
       </style>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    </head>

     <body style="font-family:verdana;font-size:10pt;">
       <%
         if(rs.next()) {
       %>
       <form action="OrderCustomer.jsp">
         <input name="itemid" type="hidden" value="<%= rs.getString(1) %>"/>
         <input name="saleprice" type="hidden" value="<%= rs.getString(4) %>"/>
         <table width="300px" border="1" style="border-collapse:collapse;background-color:#E8DCFF">
           <tr>
             <td><b>Name:</b></td>
             <td><input id="itemname" name="itemname" type="text" value="<%= rs.getString(2)%>" readonly /></td>
           </tr>
           <tr>
             <td><b>Description:</b></td>
             <td>"<%= rs.getString(3) %></td>
           </tr>
           <tr>
             <td><b>Price:</b></td>
             <td>
                 <input id="saleprice" name=""saleprice" type=text" value="<%= rs.getString(4)%>" readonly />
             </td>
           </tr>
           <tr>
             <td><b>Quantity:</b></td>
             <td>
               <input id="qty" name="qty" type="text"
               value="0"/>
             </td>
           </tr>
           <tr>
           <tr>
             <td><b>GST:</b></td>
             <td>
               <input id="gst" name="gst" type="text"
               value="" readonly/>
             </td>
           </tr>
           <tr>
             <td><b>Total:</b></td>
             <td>
               <input id="total" "name="total" type="text"
               value="" readonly/>
             </td>
           </tr>
           <tr>               
             <td></td>
             <td>
               <input type="submit" value="Checkout"/>
           </td>
           </tr>
<p></p>

        </table>
        <%
          }
        %>
        <script>
    function displayVals() {
         var mygst =0;
        var mysum =0;
        mysum = parseFloat($("#saleprice").val())*parseFloat($("#qty").val());
        mygst = mysum * 0.13;
        mysum = mysum + mygst;
        $("#gst").val(mygst.toFixed(2));
        $("#total").val(mysum.toFixed(2));
//       $("p").html("<b>gst:</b> " + mygst.toFixed(2) + "<b>   total:</b> " +mysum.toFixed(2));
    }
    $("#qty").change(displayVals);
    displayVals();
        </script>
        </body>
</html>

OrderCustomer.jsp

This JSP saves the order entry information passed by the last JSP to the OrderBean memory structure first, then retrieves those information back to display on top the screen. It also allows the user to entre their information quantity,Finally, it  passed the control to OrderConfirm.jsp.

<%--
    Document   : OrderCustomer
    Created on : 14-Mar-2012, 2:16:41 AM
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<jsp:useBean id="OrderBean" scope="session"/>
<jsp:setProperty name="OrderBean" property="itemid"/>
<jsp:setProperty name="OrderBean" property="itemname"/>
<jsp:setProperty name="OrderBean" property="saleprice"/>
<jsp:setProperty name="OrderBean" property="qty"/>
<jsp:setProperty name="OrderBean" property="gst"/>
<HTML>
     <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Order Entry 2: Customer Contact Detail</title>
        <style>
           body {
               font-family: sans-serif;
           }
           #summation {
               font-size: 18px;
               font-weight: bold;
               color:#174C68;
           }
           .txt {
               background-color: #FEFFB0;
               font-weight: bold;
               text-align: right;
           }
        </style>
    </head>
<BODY>
        You just entered the following order: <BR>
        ItemID: <%= OrderBean.getItemid() %><BR>
        ItemIName: <%= OrderBean.getItemname() %><BR>
        Saleprice: <%= OrderBean.getSaleprice() %><BR>
        Qantity: <%= OrderBean.getQty()%><BR>
        GST: <%= OrderBean.getGst() %><BR>
        Please enter your contact detail: <BR>
        <form action="OrderConfirm.jsp">
         <table width="300px" border="1" style="border-collapse:collapse;background-color:#E8DCFF">
           <tr>
             <td><b>Name:</b></td>
             <td><input id="name" name="name" type="text" value=""/></td>
           </tr>
           <tr>
           <tr>
             <td><b>Address:</b></td>
             <td><input id="address" name="address" type="text" value="" /></td>
           </tr>
           <tr>
             <td><b>Telephone:</b></td>
             <td><input id="tel" name="tel" type="text" value="" /></td>
           </tr>
           <tr>
             <td><b>Email:</b></td>
             <td><input id="email" name="email" type="text" value="" /></td>
           </tr>
           <tr>               
             <td></td>
             <td>
               <input type="submit" value="Next"/>
           </td>
           </tr>
        </table>

</BODY>
</HTML>

OrderConfirm.jsp

This JSP saves the customer information passed by the last JSP to the CustomerBean memory structure first, then retrieves those information back to display on top the screen. Finally, it  passed the control to OrderSaveServlet.

<%--
    Document   : OrderConfirm
    Created on : 14-Mar-2012, 4:30:45 AM
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<jsp:useBean id="OrderBean" scope="session"/>
<jsp:useBean id="CustomerBean" scope="session"/>
<jsp:setProperty name="CustomerBean" property="name"/>
<jsp:setProperty name="CustomerBean" property="address"/>
<jsp:setProperty name="CustomerBean" property="tel"/>
<jsp:setProperty name="CustomerBean" property="email"/>
<HTML>
     <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Order Entry</title>
        <style>
           body {
               font-family: sans-serif;
           }
           #summation {
               font-size: 18px;
               font-weight: bold;
               color:#174C68;
           }
           .txt {
               background-color: #FEFFB0;
               font-weight: bold;
               text-align: right;
           }
        </style>
    </head>
<BODY>
        You just entered the following order: <BR>
        Item ID: <%= OrderBean.getItemid() %><BR>
        Item Name: <%= OrderBean.getItemname() %><BR>
        Saleprice: <%= OrderBean.getSaleprice() %><BR>
        Qantity: <%= OrderBean.getQty()%><BR>
        GST: <%= OrderBean.getGst() %><BR>
        <BR>
        And your contact detail: <BR>
        Name: <%= CustomerBean.getName() %><BR>
        Address: <%= CustomerBean.getAddress() %><BR>
        Telephone: <%= CustomerBean.getTel()%><BR>
        Email: <%= CustomerBean.getEmail() %><BR>
        <BR>
        Click the following button to finish the order: <BR>
        <form action="OrderSaveServlet"> <input type="submit" value="Confirm"/> </form>
</BODY>
</HTML>

Order Entry System 1: JSP, Servlet, Session Bean, JQuery

In the following series, a typical web based order entry application will be discussed by using JavaSerer Pages, Java Servlets, JQuery and Java Beans (both data bean and command bean). It targets on any java based web server and relational DBMS althought it has been tested on Glassfish Open Source Server and MySQL database server only.

The series consist of three parts:

In this first part, I will discuss the component web flow chart and the starting page control first . Then, I will focus on the model part of MVC design pattern: its database tables (persistence) and its mapped memory structures Java Data Bean (volatile) .

Web Site Flow Chart

Order Entry System Web Site Flow Chart

Order Entry System Web Site Flow Chart

The order entry web application will use the list.jsp (Java Servlet and JSP Web Application 2) as the starting point. Just add the following tag onto list.jsp:

….

            <td>
               <a href="OrderServlet?id=<%= rs.getString(1) %>">
                 Order
               </a>
             </td>

….

The order entry web application will perform the following functions:

  • allow user to choose the item from inventory list and enter the quantity;
  • calculate the GST and total price on the page;
  • collect the customer information of the order;
  • save the information to database, adjust the stock quantity and generate the customer id and order id;
  • display order id once the order entry completed.

Data Model

************************************
* database model                    *
* DDL: Database Definition Language *
*************************************/
use test;

CREATE TABLE item (
 id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
 name VARCHAR(30) NOT NULL,
 description VARCHAR(30) NOT NULL,
 price DOUBLE NOT NULL,
 stock INTEGER NOT NULL) engine = InnoDB;;

CREATE TABLE customer (
 id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
 name VARCHAR(30) NOT NULL,
 address VARCHAR(200) NOT NULL,
 tel VARCHAR(15) NOT NULL,
 email VARCHAR(100) NOT NULL) engine = InnoDB;;

CREATE TABLE orders (
 id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
 itemid INTEGER NOT NULL,
 saleprice DOUBLE NOT NULL,
 gst DOUBLE NOT NULL,
 qty INTEGER NOT NULL,
 customerid INTEGER NOT NULL,
 status ENUM('RECEIVED','PROCESSED','SHIPPED','COMPLETED') DEFAULT 'RECEIVED',
 orderdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(itemid) REFERENCES item(id) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY(customerid) REFERENCES customer(id) ON DELETE CASCADE ON UPDATE CASCADE)
 engine = InnoDB;

ALTER TABLE item ADD CONSTRAINT chk_stock CHECK (stock &gt;=0);
/*******************************************************
* TRIGGER: the deduct the order qty from the stock qty *
********************************************************/

CREATE TRIGGER itemupdate BEFORE INSERT ON orders FOR EACH ROW
UPDATE item SET stock = stock - NEW.qty WHERE item.id=NEW.itemid;

OrderServlet.java

The servlet retrieves the selected item from the database based on an order id, and passed the result set to OrderEntry.jsp.

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

@WebServlet(name = "OrderServlet", urlPatterns = {"/OrderServlet"})
public class OrderServlet extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * &lt;code&gt;GET&lt;/code&gt; and
     * &lt;code&gt;POST&lt;/code&gt; methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            InitialContext ctx = new InitialContext();
            DataSource ds = (DataSource)ctx.lookup("jdbc/MySQLPool");

            Connection conn = ds.getConnection();
            Statement stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("select * from item where id="+ request.getParameter("id"));
            request.setAttribute("rs", rs);
            // activate List.jsp
            getServletContext().getRequestDispatcher("/OrderEntry.jsp").
            forward(request, response);

            stmt.close();
            conn.close();

        } catch (Exception e) {
            //e.printStackTrace();
        } finally {           
        }
    }

    // &lt;editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."&gt;
    /**
     * Handles the HTTP
     * &lt;code&gt;GET&lt;/code&gt; method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * &lt;code&gt;POST&lt;/code&gt; method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// &lt;/editor-fold&gt;
}

OrderBean.java

This bean is a memory structure with a scope of session to hold the order data chosen or entered by user from the OrderEntry.jsp.

package mybean;

public class OrderBean {
    int itemid;
    String itemname;
    double saleprice;
    double gst;
    int qty;
    public OrderBean () { }
    public void setItemid ( int value )
    {
        itemid = value;
    }
    public void setItemname ( String value )
    {
        itemname = value;
    }
    public void setSaleprice ( double value )
    {
        saleprice = value;
    }
     public void setGst ( double value )
    {
        gst = value;
    }
     public void setQty ( int value )
    {
        qty = value;
    }
    public int getItemid() { return itemid; }
    public String getItemname() { return itemname; }
    public double getSaleprice() { return saleprice; }
    public double getGst() { return gst; }
    public int getQty() { return qty; }
}</pre>
<h3>CustomerBean.java</h3>
This bean is a memory structure with a scope of session to hold the customer data entered by user from the OrderCustomer.jsp.
<pre>package mybean;

public class CustomerBean {
    String name;
    String address;
    String tel;
    String email;

    public CustomerBean () {}

    public void setName( String value )
    {
        name = value;
    }
    public void setAddress( String value )
    {
        address = value;
    }
    public void setTel( String value )
    {
        tel = value;
    }
    public void setEmail( String value )
    {
        email = value;
    }

    public String getName() { return name; }
    public String getAddress() { return address; }
    public String getTel() { return tel; }
    public String getEmail() { return email; }
}

Java Servlet and JSP Web Application 6

In the previous five posts, I provided an implementation of a typical web application in Java Servlet 3.0 and JSP, although it is in a simplified format (without input checking, validation etc).  In this post, I will conclude the series by borrowing a few drawings from a book at IBM redbooks website Servlet and JSP Programming with IBM WebSphere Studio and VisualAge for Java, in order to highlight a web application component flow (design pattern), a web application structure (component descriptions) and a web application topology (typical target runtime/production environment). I highly recommend the book to everyone.

1. Web Application Component Flow

Web Application Component Flow

Web Application Component Flow

Design Pattern: Model-View-Controller

This design follows the Model-View-Controller design pattern:

  • The JSPs (and HTML pages) provide the view.
  • The servlet is the controller.
  • The command beans represent the model.

The data beans contain the data of the model, and the view beans are helper classes to provide a data channel between the view and the model. The servlet (controller) interacts with the model (the command beans) and the view (the JSPs). The servlet controls the application flow.

2. Web Application Structure

Web Application Structure (J2EE)

Web Application Structure (J2EE)

HTML page

The input page for each step is either a static HTML page or a dynamic HTML page created from a previous step. The HTML page contains one or multiple forms that invoke a servlet for processing of the next interaction. Input data can be validated through JavaScript in the HTML page or passed to the servlet for detailed validation.

Servlet

The servlet gets control from the Application Server to perform basic control of flow. The servlet validates all the data, and returns to the browser if data is incomplete or invalid.
For valid data, processing continues. The servlet sets up and calls command beans that perform the business logic. The servlet initializes the view beans and registers them with the request block so that the JSPs can find the view beans. Depending on the results of the command beans, the servlet calls a JSP for output processing and formatting.

Command beans

Command beans control the processing of the business logic. Business logic may be imbedded in the command bean, or the command bean delegates processing to back-end or enterprise systems, such as relational databases, transaction systems (CICS, MQSeries, IMS, and so forth). A command bean may perform one specific function, or it may contain many methods, each for a specific task. Command beans may be called Task
Wrappers in such a case. Results of back-end processing are stored in data beans.

Data beans

Data beans hold the results of processing that was performed by the command bean or by back-end systems. For example, a data bean could contain an SQL result or the communication area of a CICS transaction. Data beans may not provide the necessary methods for a JSP to access the data; that is where the view beans provide the function.

View beans

View beans provide the contract between the output producing JSPs and the data beans that contain the dynamic data to be displayed in the output. Each view bean contains one or multiple data beans and provides tailored methods so that the JSP has access to the data stored in the data beans.

JSPs

The JSPs generate the output for the browser. In many cases that output again contains forms to enable the user to continue an interaction with the application. JSPs use tags to declare the view beans. Through the view beans, the JSP gets access to all the dynamic data that must be displayed in the output.

3. Web Application Topology

Web Application Topology

Web Application Topology

Java Servlet and JSP Web Application 5

Function: edit an existing inventory item

There are three programs:

  1. EditServlet.java: retrieve an existing item from the table based on id and pass it to Edit.jsp.
  2. Edit.jsp: display the item for edit, and call the UpdateServlet.java when ‘Update’ button click.
  3. UpdateServlet.java: update the detail of the item to database and display the up to date list by calling ListServlet.java.
Inventory Item Edit

Inventory Item Edit

 

EditServlet.java

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

@WebServlet(name = "EditServlet", urlPatterns = {"/EditServlet"})
public class EditServlet extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            InitialContext ctx = new InitialContext();
            DataSource ds = (DataSource)ctx.lookup("jdbc/MySQLPool");

            Connection conn = ds.getConnection();
            Statement stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("select * from item where id="+ request.getParameter("id"));
            request.setAttribute("rs", rs);
            // activate List.jsp
            getServletContext().getRequestDispatcher("/Edit.jsp").
            forward(request, response);

            stmt.close();
            conn.close();

        } catch (Exception e) {
            //e.printStackTrace();
        } finally {            
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}

Edit.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<jsp:useBean id="rs" scope="request" type="java.sql.ResultSet" />
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Inventory - Edit</title>
    </head>
     <body style="font-family:verdana;font-size:10pt;">
       <%
         if(rs.next()) {
       %>
       <form action="UpdateServlet">
         <input name="id" type="hidden" value="<%= rs.getString(1) %>"/>
         <table cellpadding="5" style="font-family:verdana;font-size:10pt;">
           <tr>
             <td><b>Name:</b></td>
             <td>
               <input name="name" type="text"
               value="<%= rs.getString(2) %>"/>
             </td>
           </tr>
           <tr>
             <td><b>Description:</b></td>
             <td>
               <input name="description" type="text"
               value="<%= rs.getString(3) %>"/>
             </td>
           </tr>
           <tr>
             <td><b>Price:</b></td>
             <td>
               <input name="price" type="text"
               value="<%= rs.getString(4) %>"/>
             </td>
           </tr>
           <tr>
             <td><b>Stock:</b></td>
             <td>
               <input name="stock" type="text"
               value="<%= rs.getString(5) %>"/>
             </td>
           </tr>
           <tr>
             <td></td>
             <td>
               <input type="submit" value="Update"/>
           </td>
           </tr>

        </table>
        <%
          }
        %>
        </body>
</html>

UpdateServlet.java

import java.io.IOException;
import java.sql.Connection;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

@WebServlet(name = "UpdateServlet", urlPatterns = {"/UpdateServlet"})
public class UpdateServlet extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            InitialContext ctx = new InitialContext();
            DataSource ds = (DataSource)ctx.lookup("jdbc/MySQLPool");

            Connection conn = ds.getConnection();
            Statement stmt = conn.createStatement();

            stmt.executeUpdate("UPDATE item " +
                    "SET name = '"+request.getParameter("name") +"',"+
                    "description = '"+request.getParameter("description")+"',"+
                    "price = "+request.getParameter("price")+","+
                    "stock = "+request.getParameter("stock")+" "+
                    "WHERE id = "+request.getParameter("id")
                    );

            // activate ListServlet
            getServletContext().getRequestDispatcher("/ListServlet").
            forward(request, response);

            stmt.close();
            conn.close();
        } catch (Exception e) {
          //  e.printStackTrace();
        } finally {            
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}