Welcome to Srini's blog

Wednesday, September 8, 2010

Sample web application using struts framework

Hello all yesterday I tried to build a simple java web application using struts and hibernate from scratch using tomcat webserver. I would like to explain step by step procedure here.

I am assuming you are already familiar with java, struts, hibernate theoretically. If not please take a low level view of all these. All my setup is build in Eclipse IDE. I wrote an ant script to build and deploy my application, So that we can directly run the build script to build/deploy the web application.

Required Tools
1. Tomcat 5.5
2. Eclipse IDE
3. Dependecy jars

About Application : My application is simple login page with server side validation and verify the login details from DB and render success/failure page. In this post i will explain how to build sample web application using struts, later post i will tell about hibernate integration to this application. I used HTML form, JSP for UI and servlets for business logic and also used beans.

Step 1 : Setup in Eclipse
====================
1. Goto File --> New --> Project
2. Select Java --> java project
3. Name the project as 'Login'
4. Click Finish.

5. Create folder structure as follows
A. Create src dir structure
i. Login/src/com/srini/action
ii. Login/src/com/srini/form
B. Create webapp dir structure
i. Login/src/com/srini/webapp
ii. Login/src/com/srini/webapp/jsp
iii. Login/src/com/srini/webapp/WEB-INF
iv. Login/src/com/srini/webapp/WEB-INF/lib
v. Login/src/com/srini/webapp/WEB-INF/classes/resources

6. Files needs to be create are
i. web.xml [Login/src/com/srini/webapp/WEB-INF]
ii. struts-config.xml [Login/src/com/srini/webapp/WEB-INF]
iii. LoginAction.java [Login/src/com/srini/action]
iv. LoginForm.java [Login/src/com/srini/form]
v. login.jsp [Login/src/com/srini/webapp/jsp]
vi. success.jsp [Login/src/com/srini/webapp/jsp]
vii. failure.jsp [Login/src/com/srini/webapp/jsp]
viii. MessageResources.properties [Login/src/com/srini/webapp/WEB- INF/classes/resources]
ix. login-build.xml [Login]
x. login-build.properties [Login]

7. Dependency jars : Please download following jars from net. I don't hv an option to upload here.
i. antlr.jar
ii. commons-beanutils.jar
iii. commons-collections.jar
iv. commons-digester.jar
v. commons-logging.jar
vi. commons-validator.jar
vii. jakarta-oro.jar
viii. jsp-api.jar
ix. servlet-api.jar
x. struts.jar

Step 2 : Each file description and code inside the file
===========================================
1.web.xml : This file has all the configuration information which we have defined for our web application. The configuration information includes the index file, the default welcome page,the mapping of our servlets including path and the extension name...etc.

ActionServlet is the central component of the Struts controller. This servlet extends the HttpServlet. This servlet basically performs two important things.
1. When the container gets start, it reads the Struts Configuration files and loads it into memory in the init() method.
2. It intercepts the HTTP request in the doGet() and doPost() method and handles it appropriately.

The configuration looks like

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>jsp/login.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>


2.struts-config.xml : The name of the struts configuration file can be configured in the web.xml file. This file is placed under the WEB-INF directory of the web application. This file has all the information about many types of Struts resources and configures their interaction.

This configuration looks like

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<form-bean name="LoginForm" type="com.srini.form.LoginForm"/>
</form-beans>

<global-forwards>
<forward name="welcome" path="/Welcome.do"/>
</global-forwards>

<action-mappings>
<action input="/jsp/login.jsp" name="LoginForm" path="/Login" scope="session" type="com.srini.action.LoginAction">
<forward name="success" path="/jsp/success.jsp" />
<forward name="failure" path="/jsp/failure.jsp" />
</action>
<action path="/Welcome" forward="/jsp/welcomeStruts.jsp"/>
</action-mappings>

<message-resources parameter="resources/MessageResource"/>
</struts-config>


This file is used to associate paths with the controller components of your application., known as Action classes like <action input="/jsp/login.jsp" name="LoginForm" path="/Login" scope="session" type="com.srini.action.LoginAction">. This tag tells the Struts ActionServlet that whenever the incoming request is http://localhost/login.do, then it must invoke the controller component LoginAction. Above, you can see that we have written .do in the URL. This mapping is done to tell the web application that whenever a request is received with the .do extension then it should be appended to the URL.

3. LoginAction.java : The execute method contains the business logic of the application. Here first we typecast the ActionForm object to LoginForm, so that we can access the form variables using the getter and setter methods. If the user name and password is same then we forward the user to the success page else we forward to the failure page.
package com.srini.action;

import java.util.List;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.srini.form.LoginForm;

/**
*
* @author srinut096@gmail.com
*/
public class LoginAction extends Action {

/* forward name="success" path="" */
private final static String SUCCESS = "success";
private final static String FAILURE = "failure";
private static Logger log = Logger.getLogger(LoginAction.class.getName());
/**
* This is the action called from the Struts framework.
* @param mapping The ActionMapping used to select this instance.
* @param form The optional ActionForm bean for this request.
* @param request The HTTP Request we are processing.
* @param response The HTTP Response we are processing.
* @throws java.lang.Exception
* @return
*/
@SuppressWarnings("unchecked")
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
LoginForm loginForm = (LoginForm) form;
log.severe("Username in Action: " + loginForm.getUserName());

if(loginForm.getUserName().equals(loginForm.getPassword())) {
return mapping.findForward(SUCCESS);
} else {
return mapping.findForward(FAILURE);
}
}
}


4. LoginForm.java : Inside the validate method, we check whether the user name and password is entered. If not the corresponding error message is displayed to the user. The error messages are configured in the Message.properties file.
package com.srini.form;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

/**
* @author srinut096@gmail.com
*/
@SuppressWarnings("serial")
public class LoginForm extends org.apache.struts.action.ActionForm {

private String userName = null;

private String password = null;

/**
*
*/
public LoginForm() {
super();
// TODO Auto-generated constructor stub
}

/**
* This is the action called from the Struts framework.
* @param mapping The ActionMapping used to select this instance.
* @param request The HTTP Request we are processing.
* @return
*/
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if (userName == null || userName.length() < password ="=" username =" userName;" password =" password;">


5. login.jsp : We use Struts HTML Tags to create login page. The form has one text field to get the user name and one password field to get the password. The form also has one submit button, which when clicked calls the login action. <html:errors /> tag is used to display the error messages to the user.
<%--
Document : login
Created on : Sep 08, 2010, 4:12:46 PM
Author : srinut096@gmail.com
--%>

<%@taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<div style="color:red">
<html:errors />
</div>
<html:form action="/Login" >
User Name :<html:text name="LoginForm" property="userName" />
Password :<html:password name="LoginForm" property="password" />
<html:submit value="Login" />
</html:form>
</body>
</html>


6. success.jsp :
<%--
Document : success
Created on : Sep 08, 2010, 4:12:46 PM
Author : srinut096@gmail.com
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>Login Success. Welcome <bean:write name="LoginForm" property="userName"></bean:write></h1>
</body>
</html>


7. failure.jsp :
<%--
Document : failure
Created on : Sep 08, 2010, 4:12:46 PM
Author : srinut096@gmail.com
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<div style="color:red">
<h1>Invalid user name <bean:write name="LoginForm" property="userName"></bean:write></h1>
</div>
</body>
</html>



8. MessageResources.properties : This file contains the error messages. The key "error.userName.required" is used in the validate function to add a new error. Since the error messages are configured in a seperate properties file they can be changed anytime without making any changes to the java files or the jsp pages.
error.userName.required = User Name is required.
error.password.required = Password is required.


9. login-build.xml : Ant build script to build the login.war
<?xml version="1.0" encoding="UTF-8"?>
<project name="Login2" default="build.war" basedir=".">
<property file="login-build.properties"/>
<property name="name" value="login2" />
<property name="build" value="${login.src.root}/build" />
<property name="war" value="${build}/war" />
<property name="source" value="${login.src.root}/src" />
<property name="lib" value="${login.src.root}/webapp/WEB-INF/lib" />

<!-- ********************************************************************** -->
<!-- Deploy war -->
<!-- ********************************************************************** -->
<target name="deploy.war" depends="build.war" >
<delete file="${login.server.root}/${name}.war" />
<delete dir="${login.server.root}/${name}" />
<copy todir="${login.server.root}">
<fileset dir="${war}">
<include name="${name}.war"/>
</fileset>
</copy>
</target>

<!-- ********************************************************************** -->
<!-- build war -->
<!-- ********************************************************************** -->
<target name="build.war" depends="compile" >
<war warfile="${war}/${name}.war" webxml="${build}/${name}/WEB-INF/web.xml">
<fileset dir="${build}/${name}">
<include name="**/**" />
</fileset>
</war>
</target>

<!-- ********************************************************************** -->
<!-- Compilation -->
<!-- ********************************************************************** -->
<target name="compile" depends="init, copy.login.webapp" >
<javac srcdir="${source}" destdir="${build}/${name}/WEB-INF/classes" debug="${javac.debug}">
<classpath refid="class.path"/>
</javac>
</target>

<path id="class.path">
<fileset dir="${lib}">
<include name="antlr.jar"/>
<include name="commons-beanutils.jar"/>
<include name="commons-collections.jar"/>
<include name="commons-digester.jar"/>
<include name="commons-logging.jar"/>
<include name="commons-validator.jar"/>
<include name="jakarta-oro.jar"/>
<include name="jsp-api.jar"/>
<include name="servlet-api.jar"/>
<include name="struts.jar"/>
</fileset>
</path>

<!-- ********************************************************************** -->
<!-- Initialization -->
<!-- ********************************************************************** -->
<target name="init" >
<delete dir="${build}" />
<mkdir dir="${build}/${name}/WEB-INF/classes"/>
<mkdir dir="${war}" />

</target>

<!-- ********************************************************************** -->
<!-- Copy struts webapp dirs -->
<!-- ********************************************************************** -->
<target name="copy.login.webapp" >
<copy todir="${build}/${name}">
<fileset dir="${login.src.root}/webapp">
<include name="**/**"/>
<exclude name="META-INF/**"/>
</fileset>
</copy>
</target>


10. login-build.properties : properties for ant build script
# ********************************************************
# Customize this one with your own root directory
# ********************************************************
login.src.root=C:/E-Folder/struts_workspace/login

login.server.root=C:/Program Files/Apache Software Foundation/Tomcat 5.5/webapps
# ********************************************************
# compilation
# ********************************************************
java.home = C:/Program Files/Java/jdk1.6.0
javac.deprecation = off
javac.nowarn = off
javac.debug = on
javac.optimize = off
jndi.prefix = java:comp/env/


Now run the application in any standard browser

1. Start Tomcat
2. http://localhost:8080/Login/login.do

2 comments:

  1. before creating folder structure we should set the environment variables. i think so. if u can plz mention that too. it will helpfull for others

    ReplyDelete
  2. I used Eclipse editor to create all the structure, So no need to set environment variables for java.

    ReplyDelete