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

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>
}