You are on page 1of 16

Simple WebAppliaction using Struts+Spring+Hibernate

Hi all,
This article presents a simple way to create a web application using
Struts+Spring+Hibernate.

I am also a newbie searching for a startup example integrating all the above said
technologies, but i was fed up as there are many tutorials on the net but explaining them
with an IDE.But here i just used an simple editor to write up my code.

Here i don't give any detailed description about the subjects regarding Struts/Spring/
Hibernate, rather i ll give a step-by-step process to build a sample application.

This example illustrates a simple application asking the user to enter his
FirstName,LastName,Mobile and City. When submitted his data is inserted into the database
and outputs all the records present in the table to the browser.

ok lets have a look over the directory structure that i used to build the application

build : This directory includes build.properties file.


src :This includes all the java files.
web :This includes all .xml and .jar files.

ok now lets have a look over build.properties and build.xml to build the application

build/build.properties

src.dir=src
dist.dir=dist
web.dir=web
lib.dir=${web.dir}/WEB-INF/lib
classes.dir=${dist.dir}/WEB-INF/classes
app.name=springex
war.dir=war
tomcat.home=C:/Program Files/Apache Software Foundation/Tomcat 5.0
tomcat.webapps=${tomcat.home}/webapps
tomcat.work=${tomcat.home}/work/Standalone/localhost

Please be sure to change the path for Tomcat home and its webapps directory if u installed
some where else.

build.xml

<?xml version="1.0"?>
<project name="StrutsSpringHibernateProject" basedir="." default="install">
<!-- Import properties file into this Build File -->
<property file="build\build.properties"/>

<!-- Set the ClassPath which is used for Compiling and Running the application -->
<path id="classpath">
<fileset dir="${lib.dir}" includes="*.jar"/>
</path>

<!-- Delete the destination Directory and War directory before Building the application -->
<target name="clean">
<delete dir="${dist.dir}"/>
<delete dir="${war.dir}"/>
</target>

<!-- Copy all the resources that are necessary for running the application -->
<target name="copy-resources">
<mkdir dir="${dist.dir}"/>
<mkdir dir="${war.dir} "/>
<copy todir="${dist.dir}">
<fileset dir="${web.dir}">
<exclude name="**/*.java"/>
</fileset>
</copy>
<copy todir="${classes.dir}">
<fileset dir="${src.dir}">
<exclude name="**/*.java"/>
</fileset>
</copy>
<mkdir dir="${classes.dir}"/>
</target>

<!-- Compile the source files -->


<target name="compile" depends="clean,copy-resources">
<javac srcdir="${src.dir}"
destdir="${classes.dir}"
includes="**/*.java"
classpathref="classpath" />
</target>

<!-- create a war file for the application -->


<target name="war" depends="compile">
<jar jarfile="${war.dir}/${app.name}.war" basedir="${dist.dir}"/>
</target>

<!-- Tomcat Related Targets -->

<!-- Clean the appliaction directory in webapps -->


<target name="tomcat-clean">
<delete dir="${tomcat.webapps}/${app.name}"/>
<delete dir="${tomcat.work}/${app.name}"/>
</target>

<!-- copy the war file created into tomcat webapps directory -->
<target name="install" depends="war,tomcat-clean">
<copy file="${war.dir}/${app.name}.war"
tofile="${tomcat.webapps}/${app.name}.war" />
</target>
</project>

As you can see the build.xml file, there are different targets defined to build the application
like clean,compile,copy-resources,tomcat-clean and install.Each has its specific task to do
and depends on others. just build it with ant and it will do all the work for you.

ok now lets have a look over the things under web directory

WEB-INF : This directory holds all the tlds,*.jar files and *.xml files
Index.jsp : The jsp page which asks for user details.
success.jsp : When the application runs file we will be forwarded to this.
failure.jsp : When application fails we will be forwarded to this.

ok now lets have a look over all these jsp pages

Index.jsp

<html>
<head>
<title>Index</title>
</head>
<body>
<form action="submitDetails.do">

<table>
<tr>
<td>FirstName :</td>
<td><input type="text" size="20" name="fname"></td>
</tr>
<tr>
<td>LastName :</td>
<td><input type="text" size="20" name="lname"></td>
</tr>
<tr>
<td>Mobile :</td>
<td><input type="text" size="20" name="mobile"></td>
</tr>
<tr>
<td>City :</td>
<td><input type="text" size="20" name="city"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="submit"></td>
</table>
</form>
</body>
</html>

success.jsp

<%@ page import="java.util.*,com.spring.bo.hibernate.*" %>


<%@ taglib uri="/WEB-INF/tlds/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/tlds/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/tlds/struts-logic.tld" prefix="logic" %>

<html>
<body>
<form>
<table>
<tr>
<td>
<table border="1">
<tr>
<td>Id</td>
<td>First Name</td>
<td>Last Name</td>
<td>Mobile</td>
</tr>

<logic:iterate name="details" id="person">

<tr>
<td><bean:write name="person" property="id"/></td>
<td><bean:write name="person" property="fname"/></td>
<td><bean:write name="person" property="lname"/></td>
<td><bean:write name="person" property="mobile"/></td>
</tr>

</logic:iterate>
</table>
</td>
</tr>
</table>
</form>
</body>
</html>

failure.jsp

<b>Failed</b>

success.jsp is used to display all the records that are present in the table, it used
<logic:iterate/> tag to iterate the list that is present in the scope which holds all the data
present in the table.

ok now lets have a look over the WEB-INF directory


lib : This directory holds all the jar files that are necessary for running this application.Just
copy all the jar files that come with spring,struts and hibernate framework.Be sure to
include all of them as there may occur anysort of error in runtime if any jar file misses.

tlds : This directory includes all the .tlds files that come with struts framework.Place all
those tlds into this directory.

Now lets have a look over all these xml files that are required to configure the application

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>application</param-name>
<param-value>ApplicationResources</param-value>
</init-param>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>0</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>Index.jsp</welcome-file>
</welcome-file-list>

<taglib>
<taglib-uri>/WEB-INF/tlds/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/tlds/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/tlds/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/tlds/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/tlds/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/tlds/struts-logic.tld</taglib-location>
</taglib>
</web-app>

This file just configures the ActionServlet and all the tlds required for the application.

struts-config.xml:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC


"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
<form-beans>
<form-bean name="personalForm"
type="org.apache.struts.validator.DynaValidatorActionForm">
<form-property name="fname" type="java.lang.String"/>
<form-property name="lname" type="java.lang.String"/>
<form-property name="mobile" type="java.lang.String"/>
<form-property name="city" type="java.lang.String"/>
<form-property name="details" type="java.util.List"/>
</form-bean>
</form-beans>

<action-mappings>
<action path="/submitDetails"
type="org.springframework.web.struts.DelegatingActionProxy"
input="/index.jsp"
name="personalForm">
<forward name="success" path="/success.jsp"/>
<forward name="failure" path="/failure.jsp"/>
</action>
</action-mappings>

<message-resources parameter="ApplicationResources"/>

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/
springBeans.xml"/>
</plug-in>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-
INF/validation.xml" />
<set-property property="stopOnFirstError" value="false" />
</plug-in>

</struts-config>

As shown above, we are using a DynaValidatorActionForm as our form bean and all there
properties set according to the inputs specified in Index.jsp.

Now just have a look over the plugin that is useful for interating with Spring.
The class 'ContextLoderPlugin' is used to include the spring context in the application and
we are specifing the location of its configuration file.

springBeans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/
dtd/spring-beans.dtd">

<beans>

<bean id="DataSource" class="org.apache.commons.dbcp.BasicDataSource">


<property
name="driverClassName"><value>oracle.jdbc.driver.OracleDriver</value></property>
<property
name="url"><value>jdbc:oracle:thin:@localhost:1521:mbos</value></property>
<property name="username"><value>madan</value></property>
<property name="password"><value>xxxx</value></property>
</bean>

<bean id="HibernateProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.query.substitutions">true 'T', false 'F'</prop>
<prop key="hibernate.c3p0.minPoolSize">5</prop>
<prop key="hibernate.c3p0.maxPoolSize">20</prop>
<prop key="hibernate.c3p0.timeout">600</prop>
<prop key="hibernate.c3p0.max_statement">50</prop>
<prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop>
</props>
</property>
</bean>

<bean id="SessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref local="DataSource"/></property>
<property name="hibernateProperties">
<ref bean="HibernateProperties" />
</property>
<property name="mappingResources">
<list>
<value>com/spring/bo/hibernate/Details.hbm.xml</value>
</list>
</property>
</bean>

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="SessionFactory"/></property>
</bean>

<bean id="personalDAOTarget" class="com.spring.bo.PersonalDAOImpl">


<property name="sessionFactory">
<ref local="SessionFactory"/>
</property>
</bean>

<bean id="personalDAO"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref
local="transactionManager"/></property>
<property name="target"><ref local="personalDAOTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="addPersonalDetails">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

<bean id="pdetails" class="com.spring.bo.hibernate.Details"/>

<bean id="personalService" class="com.spring.business.PersonalServiceImpl">


<property name="personalDAO">
<ref bean="personalDAO"/>
</property>
<property name="pdetails">
<ref bean="pdetails"/>
</property>
</bean>

<bean name="/submitDetails" class="com.spring.action.PersonalAction">


<property name="personalService">
<ref bean="personalService"/>
</property>
</bean>

</beans>

Dont just panic seeing this file, its just a spring config file holding all the details of the beans
we use. As we are integrating this with hibernate , all the configuration details regarding the
url,username,password are specified here.
It just wires all the beans accordingly to build the application.Just have a look over the xml
file and you will get to know which bean has reference to other and how they will work.

ok thats all with WEB-INF directory , now we shall see the java code in the src directory

The java source package starts with com.


Just place the ApplicationResources.properties file and log4j.xml file under the src directory.

just copy the content here into ApplicationResources.properties file

errors.required={0} is required.
errors.minlength={0} can not be less than {1} characters.
errors.maxlength={0} can not be greater than {1} characters.
errors.invalid={0} is invalid.

errors.byte={0} must be a byte.


errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.float={0} must be a float.
errors.double={0} must be a double.

errors.date={0} is not a date.


errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is an invalid credit card number.
errors.email={0} is an invalid e-mail address.

just copy the content here into log4j.xml file

<log4j:configuration debug="true">
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} [%t] %p %c %x -
%m%n"/>
</layout>
</appender>
<category name="org.apache">
<priority value="warn"/>
</category>

<category name="org.apache.axis">
<priority value="debug"/>
</category>

<root>
<priority value="debug"/>
<appender-ref ref="stdout"/>
</root>
</log4j:configuration>
k so now we have all the stuff except the java code that is required for this sample
application.

k lets see what all includes for the java stuff..

The package structure starts with com.spring .


The rest of them are included according as per the actions they do, these include
action,business and bo

action : The action class for struts reside in this package.


business : The business logic that includes in the application reside in this package.
bo : The HibernateSupport classes reside in this package.

As you can see in the above figure, except in action package the rest of business and bo
includes 2 java files, these include one interface and one implementation classes.

Ok now lets see the java classes accordingly

action.PersonalAction.java

package com.spring.action;

import java.io.*;

import java.util.List;
import java.util.LinkedList;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.struts.action.*;

import com.spring.business.*;
import com.spring.bo.hibernate.Details;

public class PersonalAction extends Action{

private PersonalService personalService;


private List personalDetails = new LinkedList();

public PersonalService getPersonalService(){


return personalService;
}
public void setPersonalService(PersonalService personalService){
this.personalService = personalService;
}

public ActionForward execute(ActionMapping mapping,


ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws
ServletException,IOException{

DynaActionForm personalForm = (DynaActionForm) form;

personalService.setDetails(personalForm);

List details = personalService.getDetails();

HttpSession session = request.getSession();


session.setAttribute("details",details);

return mapping.findForward("success");
}
}

business/PersonalService.java :

package com.spring.business;

import org.apache.struts.action.*;

import java.util.List;

import com.spring.bo.PersonalDAO;
import com.spring.bo.hibernate.Details;

public interface PersonalService{

public abstract void setDetails(DynaActionForm form);


public abstract void setPersonalDAO(PersonalDAO personalDAO);
public abstract void setPdetails(Details details);
public abstract List getDetails();

business/PersonalServiceImpl.java :

package com.spring.business;

import java.util.List;
import java.util.LinkedList;

import com.spring.bo.PersonalDAO;
import com.spring.bo.hibernate.Details;

import org.apache.struts.action.*;

public class PersonalServiceImpl implements PersonalService{

private PersonalDAO personalDAO;


private Details pdetails;

public void setPersonalDAO(PersonalDAO personalDAO){


this.personalDAO = personalDAO;
}
public void setPdetails(Details pdetails){
this.pdetails = pdetails;
}

public List personalDetails = new LinkedList();

public void setDetails(DynaActionForm personalForm){

pdetails.setFname((String)personalForm.get("fname"));
pdetails.setLname((String)personalForm.get("lname"));
pdetails.setMobile((String)personalForm.get("mobile"));
pdetails.setCity((String)personalForm.get("city"));

personalDAO.addPersonalDetails(pdetails);
}

public List getDetails(){

List details = personalDAO.getPersonalDetails();

return details;
}

bo/PersonalDAO.java

package com.spring.bo;

import java.util.List;
import com.spring.bo.hibernate.*;

public interface PersonalDAO{

public abstract void addPersonalDetails(Details details);

public abstract List getPersonalDetails();

}
bo/PersonalDAOImpl.java

package com.spring.bo;

import java.util.List;

import com.spring.bo.hibernate.Details;

import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class PersonalDAOImpl extends HibernateDaoSupport implements PersonalDAO{

public void addPersonalDetails(Details details){


getHibernateTemplate().save(details);
}

public List getPersonalDetails(){

Details details = null;

List list = getHibernateTemplate().find("from Details");


getHibernateTemplate().clear();

return list;
}
}

As shown above in the directory structure, the bo package includes another sub package
'hibernate' , this package includes the java class and mapping file for the table that we are
going to use in our application.

The java file includes all the getters and setters methods for the fields for the table and
.hbm.xml file includes the mapping details with the fields in the table.

The table i used for this application is 'PERSONAL_DETAILS' with one primary key and four
fileds that hold the information passed from Index.jsp.

bo/hibernate/Details.java

package com.spring.bo.hibernate;

public class Details{

private long id;


private String fname;
private String lname;
private String mobile;
private String city;

/*
* Setters for all the fields
*/
public void setId(long id){
this.id = id;
}
public void setFname(String fname){
this.fname = fname;
}
public void setLname(String lname){
this.lname = lname;
}
public void setMobile(String mobile){
this.mobile = mobile;
}
public void setCity(String city){
this.city = city;
}

/*
* getters for all the fields
*/
public long getId(){
return id;
}
public String getFname(){
return fname;
}
public String getLname(){
return lname;
}
public String getMobile(){
return mobile;
}
public String getCity(){
return city;
}

public String toString(){


StringBuffer sb = new StringBuffer();
sb.append("Id=").append(id);
sb.append(", fname=").append(fname);
sb.append(", lname=").append(lname);
sb.append(", mobile=").append(mobile);
sb.append(", city=").append(city);
return sb.toString();
}
}

The toString() method is useful when we are displaying the content on success.jsp when
iterating the List element.
bo/hibernate/Details.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC


"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
<class name="com.spring.bo.hibernate.Details" table="PERSONAL_DETAILS">
<id name="id" column="id" type="java.lang.Long" unsaved-value="-1">
<generator class="native"></generator>
</id>
<property name="fname" column="FIRST_NAME"/>
<property name="lname" column="LAST_NAME"/>
<property name="mobile"/>
<property name="city"/>
</class>
</hibernate-mapping>

as specified above, there is one primary key as 'id' and the rest of the propertys set
specified with there name and column. When we dont specify the column, hibernate checks
for them with the name specified, so when we have same name for both 'name' and
'column' attribute its not necessary to include the column attribute.

So thats it, now u have all the java code stuff, all the .xml files and .jsp files.

just build ur application using ant. You can see two directorys created 'dist' and 'war' as
shown below

Now just restart your tomcat and type the url ' http://localhost:8080/springex/ '

you should be able to see the screen as such if the application runs fine..

just give your inputs and submit the form, you should see the result in success page if no
error occurs during processin your request
now go back again and give another set of details and submit you should be seeing
something like this

Just have a look over the java code and xml files after running the application.

Detailed explanation is not given here as this is just a basic application and can be
understood by the ones who had an overview of all Struts/Spring/Hibernate.

Ok thats all with this example. I just did this one in order to have a pratice over all of these
three. If at all you get any errors, just copy the exception thrown and search in google, I
tried the same way and atlast i got the result. If all the JAR files are placed properly you
wouldnt get any error.

ok thnx folks for reading my post,

Regards,

Madan Chowdary Narra


9885510430
Hyderabad,India

You might also like