4/14/2012

J2EE#3 JSP + Struts MVC + Service + DAO + JDBC (Oracle) + SP (1)

Reference : http://struts.apache.org/
The Apache Struts web framework is a free open-source solution for creating Java web applications.
Web applications differ from conventional websites in that web applications can create a dynamic response. Many websites deliver only static pages. A web application can interact with databases and business logic engines to customize a response.
Web applications based on JavaServer Pages sometimes commingle database code, page design code, and control flow code. In practice, we find that unless these concerns are separated, larger applications become difficult to maintain.
One way to separate concerns in a software application is to use a Model-View-Controller (MVC) architecture. The Model represents the business or database code, the View represents the page design code, and the Controller represents the navigational code. The Struts framework is designed to help developers create web applications that utilize a MVC architecture.
The framework provides three key components:
  • A "request" handler provided by the application developer that is mapped to a standard URI.
  • A "response" handler that transfers control to another resource which completes the response.
  • A tag library that helps developers create interactive form-based applications with server pages.

Now we build project "Sample02" to realize:

JSP + Struts MVC + Service + DAO + JDBC (Oracle) + SP

First, we new the project, and then add all the libraries it needs to directory "Web Content=>WEB-INF=>lib"
Needed Jar files:
ojdbc14.jar, antlr.jar, commons-beanutils.jar, commons-digester.jar, commons-fileupload.jar, commons-logging.jar, commons-validator.jar, jakarta-oro.jar, struts.jar

Now we can start building the back end part. We can see that the Service + DAO + JDBC + SP parts do not change, so we can copy the three packages "com.company.beans", "com.company.service" and "com.company.daos" in Sample01 to Sample02. The packages can not be copied directly, so we need to new the packages first and copy the files.


Modify the Javabeans file "User.java" to extend "ActionForm":


01 package com.company.beans;
02 import org.apache.struts.action.ActionForm;
03
04 @SuppressWarnings("serial")
05 public class User extends ActionForm{
06
07     private String name;
08     private int age;
09     public String getName() {
10         return name;
11     }
12     public void setName(String name{
13         this.name = name;
14     }
15     public int getAge() {
16         return age;
17     }
18     public void setAge(int age{
19         this.age = age;
20     }
21 }

Now we should add actions into project. Create new package "com.company.actions", and create "HelloAction.java" under that package with code:


01 package com.company.actions;
02
03 import javax.servlet.http.HttpServletRequest;
04 import javax.servlet.http.HttpServletResponse;
05 import org.apache.struts.action.Action;
06 import org.apache.struts.action.ActionForm;
07 import org.apache.struts.action.ActionForward;
08 import org.apache.struts.action.ActionMapping;
09 import com.company.beans.User;
10 import com.company.services.HelloService;
11
12 public class HelloAction extends Action {
13
14     private HelloService hs;
15 
16     public HelloAction(){
17         super();
18         if(hs==null){
19             hs = new HelloService();
20         }
21     }
22     @Override
23     public ActionForward execute (ActionMapping mapping, ActionForm form,
24             HttpServletRequest request, HttpServletResponse response){
25         User user = (Userform;  // downcast 
26         request.setAttribute("userInfo", hs.process(user));
27         return mapping.findForward("result"); //forward
28     }
29 }



Next step we need to modify "Web.xml" and create "struts-config.xml" under "WebContent":


Web.xml:


01 <?xml version="1.0" encoding="ISO-8859-1"?>
02 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
03   "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
04 <web-app>
05     <display-name>Sample02</display-name>
06     <servlet>
07         <servlet-name>action</servlet-name>
08            <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
09            <init-param>
10             <param-name>config</param-name>
11             <param-value>/WEB-INF/struts-config.xml</param-value>
12            </init-param>
13              <init-param>
14                  <param-name>debug</param-name>
15                  <param-value>1</param-value>
16              </init-param>
17              <init-param>
18                  <param-name>detail</param-name>
19                  <param-value>1</param-value>
20         </init-param>
21         <load-on-startup>1</load-on-startup>
22     </servlet>
23     <servlet-mapping>
24         <servlet-name>action</servlet-name>
25         <url-pattern>*.do</url-pattern>
26     </servlet-mapping>
27     <welcome-file-list>
28         <welcome-file>index.jsp</welcome-file>
29     </welcome-file-list>
30 </web-app>


struts-config.xml:
01 <?xml version="1.0" encoding="UTF-8"?>
02 <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
03 <struts-config>
04     <form-beans>
05         <form-bean name="userForm" type="com.mercury.beans.User"/>
06     </form-beans>
07     <action-mappings>
08         <action name="userForm" path="/hello" type="com.mercury.actions.HelloAction"
09             scope="request" input="/hello.jsp">
10             <forward name="result" path="/result.jsp" />
11         </action>
12          <action path="/index" type="org.apache.struts.actions.ForwardAction"
13             parameter="/hello.jsp">
14         </action>
15     </action-mappings>
16 
</struts-config>    




Now we copy the "hello.jsp" and "result.jsp" from Sample01 to Sample02.
In hello.jsp, we need to modify the code to use struts html tag, bean tag and logic tag.
Also, we should add validation. Create a new package in src with name "com.company.validate". In the package, create a File "ApplicationResources.properties"


hello.jsp:


01 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
02     pageEncoding="ISO-8859-1"%>
03 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
04 <%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
05 <%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
06
07 <html>
08 <head>
09 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
10 <title>Hello Page</title>
11 <style type = "text/css">
12     .error {color:red}
13 </style>
14
15 </head>
16
17 <body>
18 <h2><font color="blue">Sample02: JSP + Struts MVC + Service + DAO + JDBC + SP</font></h2>
19 <p class="error"><html:messages id="errors">
20     <bean:write name="errors" />
21 </html:messages></p>
22
23 <html:form action="/hello">
24     <table>
25         <tr>
26             <td><bean:message key="user.name" /></td>
27             <td><html:text property="name" /></td>
28         </tr>
29         <tr>
30             <td><bean:message key="user.age" /></td>
31             <td><html:text property="age" value="" /></td>
32         </tr>
33         <tr>
34             <td></td>
35             <td><html:reset value="Clear" /> <html:submit value="Submit" />
36             </td>
37         </tr>
38     </table>
39 </html:form>
40 </body>
41 </html>



result.jsp:
01 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
02     pageEncoding="ISO-8859-1"%>
03 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
04 <%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
05 <%@taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
06
07 <html>
08 <head>
09 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
10 <title>Insert title here</title>
11 </head>
12 <body>
13 <jsp:useBean id = "userInfo" scope= "request" class = "com.company.beans.UserInfo"/>
14
15     <h2><font color="blue"><jsp:getProperty name = "userInfo" property = "msg"/></font></h2>
16    
17     <table width = "200" border = "1">
18     <tr>
19         <th><bean:message key = "user.name"/></th>
20         <th><bean:message key = "user.age"/></th>
21     </tr>
22     <logic:iterate id="user" name="userInfo" property="users"
23         type="com.company.beans.User" scope="request">
24             <tr>
25                 <td><bean:write name="user" property="name"/></td>
26                 <td><bean:write name="user" property="age"/></td>
27             </tr>
28     </logic:iterate>
29
30     </table>
31    
32 </body>
33 </html>



ApplicationResources.properties


1 #User Information
2 user.name=User Name
3 user.age=User Age
4
5 #Error message
6 error.name = Invalid name
7 error.age = Invalid age



Modify "User.java"


01 package com.company.beans;
02 import javax.servlet.http.HttpServletRequest;
03
04 import org.apache.struts.action.ActionErrors;
05 import org.apache.struts.action.ActionMapping;
06 import org.apache.struts.action.ActionMessage;
07 import org.apache.struts.validator.ValidatorForm;
08
09 @SuppressWarnings("serial")
10 public class User extends ValidatorForm{
11
12     private String name;
13     private int age;
14     public String getName() {
15         return name;
16     }
17     public void setName(String name{
18         this.name = name;
19     }
20     public int getAge() {
21         return age;
22     }
23     public void setAge(int age{
24         this.age = age;
25     }
26    
27     @Override
28     public ActionErrors validate(ActionMapping mapping, HttpServletRequest request{
29         ActionErrors actionErrors = new ActionErrors();
30         if (name==null || name.length()<3{
31             actionErrors.add("name", new ActionMessage("error.name"));
32         }
33         if (age<=0{
34             actionErrors.add("age", new ActionMessage("error.age"));
35         }
36         return actionErrors;
37         }
38    
39 }



Now we are done! We can run the "Hello.jsp" to test the project. It works fine.

4/11/2012

J2EE#2 Target: JSP + Servlet + Service + DAO + JDBC (Oracle) + SP (3)

In J2EE#2 Target: JSP + Servlet + Service + DAO + JDBC (Oracle) + SP (2),
I've realized JSP + Servlet + Service. Now the remaining is Database part. DAO is a design pattern used to deal with the database.
What needs to be mentioned first is that, in J2EE, when adding external JAR files, we need to copy the JAR files under the directory "WEB-INF\lib". So first we copy the JAR files "ojdbc14.jar" under this directory.
Then new a new package under src "com.company.daos".
Copy "JDBCUtil.java" under the package. Please refer to my previous post:

JDBC configuration and implementation (Oracle&Eclipse)


Then New a java file "HelloDao.java".
Code:
01 package com.company.daos;
02
03 import java.util.*;
04 import java.sql.*;
05 import oracle.jdbc.OracleTypes;
06 import com.company.beans.User;
07
08 public class HelloDao {
09
10     public void save(User user{
11         try {
12             Connection conn = JDBCUtil.getConnection();
13             String sp = "{? = call saveUser(?,?)}";
14             CallableStatement cs = conn.prepareCall(sp);
15             cs.registerOutParameter(1, Types.INTEGER); // output
16             cs.setString(2, user.getName()); // input
17             cs.setInt(3, user.getAge());
18             cs.execute();
19             cs.close();
20
21         } catch (Exception e{
22             e.printStackTrace();
23         }
24     }
25
26     public List<User> query() {
27         List<User> list = new ArrayList<User>();
28         String sp = "{? = call queryUser()}";
29         try {
30             Connection conn = JDBCUtil.getConnection();
31             CallableStatement cs = conn.prepareCall(sp);
32             cs.registerOutParameter(1, OracleTypes.CURSOR);    
33             cs.execute();
34             ResultSet rs = (ResultSetcs.getObject(1);
35            
36             while (rs.next()) {
37                 User user = new User();
38                 user.setName(rs.getString("Name"));
39                 user.setAge(rs.getInt("Age"));
40                 list.add(user);
41             }
42             rs.close();
43         } catch (Exception e{
44             e.printStackTrace();
45         }
46         return list;
47     }
48
49 }

The code are immigrated from "OracleTest3.java". Refer to 

Statement, PreparedStatement, CallableStatement


Actually, until now, the DAO + JDBC(Oracle) + SP are done. The left part is that we need to modify the code and connect all the parts together.


As a result, the web page will show one message with the input name and age, along with one table that contains all the name and age stored in the database.
We can see that the return data can also be wrapped with JavaBeans. One field is the message and the other field is the list of User. So first, we new "UserInfo.java" in package "com.company.beans", with code:
01 package com.company.beans;
02 import java.util.*;
03 
04 public class UserInfo {
05 
06     private String msg;
07     private List<User> users;
08     public String getMsg() {
09         return msg;
10     }
11     public void setMsg(String msg) {
12         this.msg = msg;
13     }
14     public List<User> getUsers() {
15         return users;
16     }
17     public void setUsers(List<User> users) {
18         this.users = users;
19     }    
20 } 


And we should modify "HelloService.java" to connect to DAO. We should also use the thought of Singleton. Code is like this:
01 package com.company.services;
02 import com.company.beans.*;
03 import com.company.daos.*;
04
05 public class HelloService {
06     private HelloDao hd;
07
08     public HelloService(){
09         //System.out.println("Create an instance of HelloService");
10         if(hd == null){
11             hd = new HelloDao();
12         }
13     }
14     public String sayHello1(User user){
15         StringBuffer sb = new StringBuffer();
16         sb.append("<HTML><body>");
17         sb.append("<h2><font color = blue>");
18         sb.append("Hello " + user.getName() + ", with age " + user.getAge() + ", welcome to J2EE!");
19         sb.append("</h2></font>");
20         sb.append("</body></HTML>");
21         return sb.toString();
22     }
23     public String sayHello2 (User user){
24         return "Hello " + user.getName() + "(" + user.getAge() + "), welcome to J2EE!";
25     }
26    
27     public UserInfo process(User user){
28         hd.save(user);
29         UserInfo userInfo = new UserInfo();
30         userInfo.setMsg(this.sayHello2(user));
31         userInfo.setUsers(hd.query());
32         return userInfo;
33     }
34 }



Now we change "HelloServlet.servlet" and "hello.jsp" to show the result page.
In "hello.jsp", we modify the method in form to "post" to test doPost function.


11 <form action = "HelloServlet" method="post">


In "HelloServlet.servlet", we add below code to doPost method:


1 protected void doPost(HttpServletRequest request, HttpServletResponse responsethrows ServletException, IOException{
2         // TODO Auto-generated method stub
3         User user = parse(request);
4         request.setAttribute("userInfo", hs.process(user));
5         String url = "/result.jsp";
6         RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher(url);
7         dispatcher.forward(request, response);
8     }



At last, we create "result.jsp" to show the result.


01 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
02     pageEncoding="ISO-8859-1"%>
03 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
04 <html>
05 <head>
06 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
07 <title>Insert title here</title>
08 </head>
09 <body>
10 <%@page import = "com.company.beans.User" %>
11 <jsp:useBean id = "userInfo" scope= "request" class = "com.company.beans.UserInfo"/>
12
13     <h2><font color="blue"><jsp:getProperty name = "userInfo" property = "msg"/></font></h2>
14     <table width = "200" border = "1">
15     <tr>
16         <th>Name</th>
17         <th>Age</th>
18     </tr>
19     <%
20        for (User user:userInfo.getUsers()){
21            out.print("<tr>");
22            out.print("<td>" + user.getName() + "</td>");
23            out.print("<td>" + user.getAge() + "</td>");
24            out.print("</tr>");
25           
26        }
27     %>
28 </body>
29 </html>



Until now, we are almost done. We have connected all the parts.


JSP + Servlet + Service + DAO + JDBC (Oracle) + SP
The only two left parts are that, first, we do not have input validation, second, we should prevent manually out.print HTML tags. We should only out.print specific value. To realize this, we can use JSTL to display result.


1. Apply Validation
To make basic logic algorithm at the front end, we need to use JavaScript.
New "validate,js" under Web Content:
Right click on "Web Content" => New => Other => Web => JavaScript


Code:


01 function validate_required(field, alertMsg{  // Validate a required field
02     with (field{
03         if (value==null || value==""{
04             alert("Please fill in the '"+alertMsg+"' box.");
05             return false;
06         }
07         return true;
08     }
09 }
10 function validate_int(field, alertMsg{  // Validate an integer field
11     with (field{
12         var num = parseInt(value);
13         if (isNaN(num) || num<0{
14             alert(alertMsg);
15             return false;
16         }
17         return true;
18     }
19 }
20 function validate_Form(thisForm{   // Validate the form
21     with (thisForm{
22            /* code */
23         if(!validate_required(name, "Name")){
24            name.focus();
25            return false;
26         }
27         if(!validate_required(age, "Age")){
28            age.focus();
29            return false;
30         }
31         if(!validate_int(age, "Invalid age")){
32            age.focus();
33            return false;
34         }
35     }
36     return true;
37 }



Modify "hello.jsp": 


01 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
02     pageEncoding="ISO-8859-1"%>
03 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
04 <html>
05 <head>
06 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
07 <title>Insert title here</title>
08 <script language="javascript" src="validate.js"></script>
09 </head>
10 <body>
11 <h2><font color="blue">Sample01: JSP + Servlet + Service + DAO + JDBC + SP</font></h2>
12 <form action="HelloServlet" method="post" onsubmit="return validate_Form(this);">
13     <table>
14         <tr>
15             <td>Name :</td>
16             <td><input type="text" name="name" /></td>
17         </tr>
18         <tr>
19             <td>Age :</td>
20             <td><input type="text" name="age" /></td>
21         </tr>
22         <tr>
23             <td></td>
24             <td>
25                 <input type="reset" value="Clear" />
26                 <input type="submit" value="Submit" />
27             </td>
28         </tr>
29     </table>
30 </form>
31 </body>
32 </html>



Now we can check the validation:




It works fine.


2. Apply JSTL


To use JSTL, we need to add external jar files.
Copy "c.tld" under "WEB-INF", "jstl.jar" and "standard.jar" under "WEB-INF=>lib"


Modify "Web.xml", add block:


01 <?xml version="1.0" encoding="UTF-8"?>
02 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
03   <display-name>Sample01</display-name>
04   <jsp-config>
05     <taglib>
06         <taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
07         <taglib-location>/WEB-INF/c.tld</taglib-location>
08       </taglib>
09   </jsp-config>

10   <welcome-file-list>
11     <welcome-file>index.html</welcome-file>
12     <welcome-file>index.htm</welcome-file>
13     <welcome-file>index.jsp</welcome-file>
14     <welcome-file>default.html</welcome-file>
15     <welcome-file>default.htm</welcome-file>
16     <welcome-file>default.jsp</welcome-file>
17   </welcome-file-list>
18   <servlet>
19     <description></description>
20     <display-name>HelloServlet</display-name>
21     <servlet-name>HelloServlet</servlet-name>
22     <servlet-class>com.company.servlets.HelloServlet</servlet-class>
23   </servlet>
24   <servlet-mapping>
25     <servlet-name>HelloServlet</servlet-name>
26     <url-pattern>/HelloServlet</url-pattern>
27   </servlet-mapping>
28 </web-app>



Modify "result.jsp":


01 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
02     pageEncoding="ISO-8859-1"%>
03 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
04 <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
05 <html>
06 <head>
07 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
08 <title>Insert title here</title>
09 </head>
10 <body>
11 <%@page import = "com.company.beans.User" %>
12 <jsp:useBean id = "userInfo" scope= "request" class = "com.company.beans.UserInfo"/>
13
14     <h2><font color="blue">${userInfo.msg}</font></h2>
15     <table width = "200" border = "1">
16     <tr>
17         <th>Name</th>
18         <th>Age</th>
19     </tr>
20     <c:forEach var="user" items = "${userInfo.users}">
21         <tr>
22             <td>${user.name}</td>
23             <td>${user.age}</td>
24         </tr>
25     </c:forEach>

26     </table>
27 </body>
28 </html>



Until now, all the codes are done.
Result:


We successfully realize :


JSP + Servlet + Service + DAO + JDBC (Oracle) + SP