CRUD Operations using JPA

I will show how to perform four basic functions, create, read, update and delete (CRUD) on relational database application by using JPA in this post.

I only include two programs in the following. Full source codes can be cloned from https://github.com/henry416/jpatest.
1) Student.java: to define a new entity class;
2) StudentTest.java: to perform CRUD operations;

1. Entity Class: Student.java

package henry416.domain;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Student {
	@Id
	private int id;

	private String name;
	
	private double gpa;
	
	public Student() {}

	public Student(int id) {
		this.id = id;
	}
	
	public Student(int id, String name, double gpa) {
		this.id = id;
		this.name = name;
		this.gpa = gpa;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public double getGpa() {
		return gpa;
	}
	
	public void setGpa(double gpa) {
		this.gpa = gpa;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", gpa="
				+ gpa + "]";
	}

}

2. CRUD Operations: StudentTest.java

package henry416.jpa;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import henry416.domain.Student;

public class StudentTest {

	private EntityManager manager;

	public StudentTest(EntityManager manager) {
		this.manager = manager;
	}
 
	public static void main(String[] args) {
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("persistenceUnit");
		EntityManager manager = factory.createEntityManager();
		StudentTest test = new StudentTest(manager);

		EntityTransaction tx = manager.getTransaction();
		System.out.println("1. create student records");
		tx.begin();
		try {
			test.createStudents();
		} catch (Exception e) {
			e.printStackTrace();
		}
		tx.commit();

		System.out.println("2. read student records");
		test.readStudents();

		System.out.println("3. update a student record");
		tx.begin();
		try {
			test.updateStudent();
		} catch (Exception e) {
			e.printStackTrace();
		}
		tx.commit();		

		System.out.println("4. delete a student record");
		tx.begin();
		try {
			test.deleteStudent();
		} catch (Exception e) {
			e.printStackTrace();
		}
		tx.commit();		
		
		System.out.println("5. delete all student records");
		tx.begin();
		try {
			test.deleteStudents();
		} catch (Exception e) {
			e.printStackTrace();
		}
		tx.commit();		
		
		System.out.println("=> done");
	}

	private void createStudents() {
		// insert a few records
		manager.persist(new Student(1,"Jack Jackson",3.28));
		manager.persist(new Student(2,"Tom Thomson",3.56));
		manager.persist(new Student(3,"Dave Davison",3.65));
		manager.persist(new Student(4,"Neil Nelson",3.56));
		manager.persist(new Student(5,"Mark Markson",3.78));		
	}

	private void readStudents() {
		List<Student> resultList = manager.createQuery("Select s From Student s order by s.id", Student.class).getResultList();
		System.out.println("num of students:" + resultList.size());
		for (Student next : resultList) {
			System.out.println("=> " + next);
		}
	}

	private void updateStudent() {
		// update a student record
		Student stu = manager.find(Student.class, 2);
        	if (stu != null) {
                  System.out.println("from => "+stu);  
        	  stu.setName("Thomas Thomson");
                  stu.setGpa(3.99);
                  System.out.println("to => "+stu);
        	}
	}
	
	private void deleteStudent() {
		// delete ONE record
		Student stu = manager.find(Student.class, 2);
		System.out.println("remove=> "+stu);
		if (stu != null) {
		   manager.remove(stu);
		}

	}
	
	private void deleteStudents() {
		// delete all records
		int deletedCount = manager.createQuery("DELETE FROM Student").executeUpdate();
		System.out.println("total num of records removed => "+deletedCount);
	}
}

3. Result

The following is the execution results:

1. create student records
2. read student records
num of students:5
=> Student [id=1, name=Jack Jackson, gpa=3.28]
=> Student [id=2, name=Tom Thomson, gpa=3.56]
=> Student [id=3, name=Dave Davison, gpa=3.65]
=> Student [id=4, name=Neil Nelson, gpa=3.56]
=> Student [id=5, name=Mark Markson, gpa=3.78]
3. update a student record
from => Student [id=2, name=Tom Thomson, gpa=3.56]
to => Student [id=2, name=Thomas Thomson, gpa=3.99]
4. delete a student record
remove=> Student [id=2, name=Thomas Thomson, gpa=3.99]
5. delete all student records
total num of records removed => 4
=> done

Standalone JPA Project Using Java SE: A Maven Way

In this post, I will show how to create a simple JPA application by using maven and Java SE JDK. All the other libraries will be taken care of by the remote repository in maven, which includes eclipselink and embedded derby db.

I will be focusing on how to use maven to generate, what project structure and programs created, how to execute the application, how to verify the database objects, and what targets can be deployed.

I hope this will help you get started, especially without using any IDEs like Eclipse, Netbean etc.

I won’t go to explain what JPA is. There are many resources and books available.

1. Generate JPA App in Seconds

Make sure to enter ’46’ as artifactID (46 is for com.github.lalyos:standalone-jpa-eclipselink-archetype) when asked in the following:

mvn archetype:generate -DgroupId=henry416 -DartifactId=test1

.................

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 354: 46
Choose com.github.lalyos:standalone-jpa-eclipselink-archetype version: 
1: 0.0.1
2: 0.0.2
Choose a number: 2: 2
[INFO] Using property: groupId = henry416
[INFO] Using property: artifactId = test1
Define value for property 'version':  1.0-SNAPSHOT: : 
[INFO] Using property: package = henry416
Confirm properties configuration:
groupId: henry416
artifactId: test1
version: 1.0-SNAPSHOT
package: henry416
 Y: : 
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: standalone-jpa-eclipselink-archetype:0.0.2
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: henry416
[INFO] Parameter: artifactId, Value: test1
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: henry416
[INFO] Parameter: packageInPathFormat, Value: henry416
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: henry416
[INFO] Parameter: groupId, Value: henry416
[INFO] Parameter: artifactId, Value: test1
[INFO] project created from Archetype in dir: /home/henry/Test/jpatest/test1
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:42.092s
[INFO] Finished at: Thu Mar 06 21:10:38 EST 2014
[INFO] Final Memory: 10M/25M
[INFO] ------------------------------------------------------------------------

2. Project Structures Generated

henry@brimley:~/Test/jpatest/test1$ ls -ld $(find .)
drwxr-xr-x 3 henry henry 4096 2014-03-06 22:37 .
-rw-r--r-- 1 henry henry   70 2014-03-06 21:10 ./ij.properties
-rw-r--r-- 1 henry henry 1185 2014-03-06 21:10 ./pom.xml
-rwx------ 1 henry henry   60 2014-03-06 21:10 ./run.sh
-rwx------ 1 henry henry  107 2014-03-06 21:10 ./show-derby.sh
drwxr-xr-x 3 henry henry 4096 2014-03-06 21:10 ./src
drwxr-xr-x 4 henry henry 4096 2014-03-06 21:10 ./src/main
drwxr-xr-x 3 henry henry 4096 2014-03-06 21:10 ./src/main/java
drwxr-xr-x 4 henry henry 4096 2014-03-06 21:10 ./src/main/java/henry416
drwxr-xr-x 2 henry henry 4096 2014-03-06 21:10 ./src/main/java/henry416/domain
-rw-r--r-- 1 henry henry  928 2014-03-06 21:10 ./src/main/java/henry416/domain/Department.java
-rw-r--r-- 1 henry henry  992 2014-03-06 21:10 ./src/main/java/henry416/domain/Employee.java
drwxr-xr-x 2 henry henry 4096 2014-03-06 21:10 ./src/main/java/henry416/jpa
-rw-r--r-- 1 henry henry 1597 2014-03-06 21:10 ./src/main/java/henry416/jpa/JpaTest.java
drwxr-xr-x 3 henry henry 4096 2014-03-06 21:10 ./src/main/resources
drwxr-xr-x 2 henry henry 4096 2014-03-06 21:10 ./src/main/resources/META-INF
-rw-r--r-- 1 henry henry 1205 2014-03-06 21:10 ./src/main/resources/META-INF/persistence.xml

The source codes you may be interested in the following separate links:
./pom.xml
./src/main/resources/META-INF/persistence.xml
./src/main/java/henry416/domain/Department.java
./src/main/java/henry416/domain/Employee.java
./src/main/java/henry416/jpa/JpaTest.java

3. Test Run

henry@brimley:~/Test/jpatest/test1$ cat run.sh
mvn compile exec:java -Dexec.mainClass=henry416.jpa.JpaTest

henry@brimley:~/Test/jpatest/test1$ chmod 700 *.sh

henry@brimley:~/Test/jpatest/test1$ ./run.sh 
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building test1 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ test1 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ test1 ---
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 3 source files to /home/henry/Test/jpatest/test1/target/classes
[INFO] 
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) @ test1 >>>
[INFO] 
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) @ test1 <<<
[INFO] 
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ test1 ---
num of employess:2
next employee: Employee [id=3, name=Captain Nemo, department=java]
next employee: Employee [id=2, name=Jakab Gipsz, department=java]
.. done
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 27.590s
[INFO] Finished at: Thu Mar 06 21:15:27 EST 2014
[INFO] Final Memory: 24M/61M
[INFO] ------------------------------------------------------------------------

4. Result

henry@brimley:~/Test/jpatest/test1$ cat show-derby.sh 
mvn dependency:copy-dependencies
java -cp 'target/dependency/*' org.apache.derby.tools.ij -p ij.properties

henry@brimley:~/Test/jpatest/test1$ ./show-derby.sh 
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building test1 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:copy-dependencies (default-cli) @ test1 ---
[INFO] Copying eclipselink-2.2.1.jar to /home/henry/Test/jpatest/test1/target/dependency/eclipselink-2.2.1.jar
[INFO] Copying derbytools-10.8.2.2.jar to /home/henry/Test/jpatest/test1/target/dependency/derbytools-10.8.2.2.jar
[INFO] Copying derby-10.8.2.2.jar to /home/henry/Test/jpatest/test1/target/dependency/derby-10.8.2.2.jar
[INFO] Copying javax.persistence-2.0.3.jar to /home/henry/Test/jpatest/test1/target/dependency/javax.persistence-2.0.3.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.026s
[INFO] Finished at: Thu Mar 06 21:17:51 EST 2014
[INFO] Final Memory: 8M/21M
[INFO] ------------------------------------------------------------------------
ij version 10.8
CONNECTION0* - 	jdbc:derby:simpleDb
* = current connection
ij> show schemas;
TABLE_SCHEM                   
------------------------------
APP                           
NULLID                        
SQLJ                          
SYS                           
SYSCAT                        
SYSCS_DIAG                    
SYSCS_UTIL                    
SYSFUN                        
SYSIBM                        
SYSPROC                       
SYSSTAT                       
TEST1                         

12 rows selected
ij> select * from TEST1.DEPARTMENT;
ID                  |NAME                
-----------------------------------------
1                   |java                

1 row selected
ij> select * from TEST1.EMPLOYEE;
ID                  |NAME                |DEPARTMENT_ID       
--------------------------------------------------------------
3                   |Captain Nemo        |1                   
2                   |Jakab Gipsz         |1                   

2 rows selected
ij> exit;

5. Deployment Target

henry@brimley:~/Test/jpatest/test1/target$ ls -ld $(find .)
drwxr-xr-x 4 henry henry    4096 2014-03-06 21:17 .
drwxr-xr-x 4 henry henry    4096 2014-03-06 21:15 ./classes
drwxr-xr-x 4 henry henry    4096 2014-03-06 21:15 ./classes/henry416
drwxr-xr-x 2 henry henry    4096 2014-03-06 21:15 ./classes/henry416/domain
-rw-r--r-- 1 henry henry    1691 2014-03-06 21:15 ./classes/henry416/domain/Department.class
-rw-r--r-- 1 henry henry    1888 2014-03-06 21:15 ./classes/henry416/domain/Employee.class
drwxr-xr-x 2 henry henry    4096 2014-03-06 21:15 ./classes/henry416/jpa
-rw-r--r-- 1 henry henry    3080 2014-03-06 21:15 ./classes/henry416/jpa/JpaTest.class
drwxr-xr-x 2 henry henry    4096 2014-03-06 21:15 ./classes/META-INF
-rw-r--r-- 1 henry henry    1205 2014-03-06 21:15 ./classes/META-INF/persistence.xml
drwxr-xr-x 2 henry henry    4096 2014-03-06 21:17 ./dependency
-rw-r--r-- 1 henry henry 2671577 2014-03-06 21:17 ./dependency/derby-10.8.2.2.jar
-rw-r--r-- 1 henry henry  174969 2014-03-06 21:17 ./dependency/derbytools-10.8.2.2.jar
-rw-r--r-- 1 henry henry 6412045 2014-03-06 21:17 ./dependency/eclipselink-2.2.1.jar
-rw-r--r-- 1 henry henry  126856 2014-03-06 21:17 ./dependency/javax.persistence-2.0.3.jar

6. Run As Java Application

henry@brimley:~/Test/jpatest/test1$ cd target/classes
henry@brimley:~/Test/jpatest/test1/target/classes$ java -cp '../dependency/*' henry416.jpa.JpaTest
num of employess:2
next employee: Employee [id=3, name=Captain Nemo, department=java]
next employee: Employee [id=2, name=Jakab Gipsz, department=java]
.. done

7. Summary

By using maven, it’s pretty easy to create a project structure for a JPA application (Kudos to you Lajos Papp). By replacing those POJO entity classes with your own classes, modifying persistence.xml to your local database and pom.xml to the latest maven repository, you can code a real world java application in JPA. I hope this will make JPA programming more interesting.

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

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