12
EDN » JBuilder » Web Technologies Struts, Hibernate and Spring: A guide to creating a dynamic web application By: Christopher Moeller Abstract: A tutorial which uses the Struts, Hibernate and Spring frameworks to create a complete website registration page. Note: This tutorial does not necessarily require the use of an IDE, but explanations (in green) will be provided that assume the use of the JBuilder IDE (version 2006 or prior). This document assumes basic knowledge of Java and web applications. I. Creating a project Using JBuilder, complete the following steps to setup a project in the IDE: 1. Create a new project in JBuilder with a unique name. (e.g. StrtusTutorial.jpx). 2. Set the server for the project in the 'Project Properties' to Tomcat 5.5. 3. Create a new web module with a unique name (e.g. StrutsTutorial) -- by default, this will determine the name of the WAR file that will be eventually created. Then, choose 'Servlet 2.4' and 'JSP 2.0' standards (Step 2 of 3). Next, make sure to check 'Struts 1.2' and 'Validation' (Step 3 of 3). Finally, click finish. Now, let's take stock of our project. You should have a directory under your project with a name that matches your web module name. In that directory you will have only a WEB-INF folder. Within that folder you will have several (xml and tdl) files, like so: <Web Module> WEB-INF strtus-config.xml validation.xml validation-rules.xml web.xml struts-bean.tld struts-html.tld struts-logic.tld struts-nested.tld struts-tiles.tld The .tld files are located within the struts JAR files. JBuilder automatically copies them to your web module's WEB-INF folder after you selected the Struts framework during the web module wizard. If you are not using JBuilder or an IDE, you will need to download Struts 1.2, and then open the struts.jar using WinZip (or other unarchiving tool), find the.tld files (usually under Struts.jar/META- INF/tlds), and extract them to your <web module>/WEB-INF folder. The xml files are provided below: struts-config.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd"> <struts-config> <message-resources parameter="ApplicationResources" /> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB- INF/validation.xml" /> </plug-in> </struts-config> Note: The struts-config.xml file is the configuration file that defines the flow in Struts web applications. This configuration file defines data sources (parameters needed to use JDBC objects), form beans (mappings/definitions for beans that hold information that has been submitted by the user from a web form), forwards (mappings that provide an easy way to send the user to a specified page depending on business logic) and actions (mapping to an object that handles business logic). validation.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN" "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd"> <form-validation /> Note: The validator.xml defines specific validations which apply to form beans. validation-rules.xml <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN" I. II A fi II pa IV cr us V V V S V IX COMMUNITIES ARTICLES BLOGS RESOURCES DOWNLOADS HELP LOG ON | | EMBARCADERO HOME ENGLISH LOCATION Share Watch, Follo Connect w 2/8/2011 Struts, Hibernate and Spring: A guide t… edn.embarcadero.com/article/36524?b… 1/12

Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

Embed Size (px)

DESCRIPTION

Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

Citation preview

Page 1: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

EDN » JBuilder » Web Technologies

Struts, Hibernate and Spring: A guide to creating a dynamic web application

By: Christopher Moeller

Abstract: A tutorial which uses the Struts, Hibernate and Spring frameworks to create a complete website registration page.

Note: This tutorial does not necessarily require the use of an IDE, but explanations (in green) will be provided that assumethe use of the JBuilder IDE (version 2006 or prior). This document assumes basic knowledge of Java and web applications.

I. Creating a project

Using JBuilder, complete the following steps to setup a project in the IDE:

1. Create a new project in JBuilder with a unique name. (e.g. StrtusTutorial.jpx).2. Set the server for the project in the 'Project Properties' to Tomcat 5.5.3. Create a new web module with a unique name (e.g. StrutsTutorial) -- by default, this will determine

the name of the WAR file that will be eventually created. Then, choose 'Servlet 2.4' and 'JSP 2.0'standards (Step 2 of 3). Next, make sure to check 'Struts 1.2' and 'Validation' (Step 3 of 3). Finally,click finish.

Now, let's take stock of our project. You should have a directory under your project with a name that matches your web modulename. In that directory you will have only a WEB-INF folder. Within that folder you will have several (xml and tdl) files, like so:

<Web Module>

WEB-INF

strtus-config.xml

validation.xml

validation-rules.xml

web.xml

struts-bean.tld

struts-html.tld

struts-logic.tld

struts-nested.tld

struts-tiles.tld

The .tld files are located within the struts JAR files. JBuilder automatically copies them to your web module's WEB-INF folder after youselected the Struts framework during the web module wizard. If you are not using JBuilder or an IDE, you will need to downloadStruts 1.2, and then open the struts.jar using WinZip (or other unarchiving tool), find the.tld files (usually under Struts.jar/META-INF/tlds), and extract them to your <web module>/WEB-INF folder.

The xml files are provided below:

struts-config.xml:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD StrutsConfiguration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">

<struts-config><message-resources parameter="ApplicationResources" /><plug-in className="org.apache.struts.validator.ValidatorPlugIn"><set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" /></plug-in></struts-config>

Note: The struts-config.xml file is the configuration file that defines the flow in Struts webapplications. This configuration file defines data sources (parameters needed to use JDBC objects),form beans (mappings/definitions for beans that hold information that has been submitted by theuser from a web form), forwards (mappings that provide an easy way to send the user to aspecified page depending on business logic) and actions (mapping to an object that handlesbusiness logic).

validation.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD CommonsValidator Rules Configuration 1.1.3//EN""http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">

<form-validation />

Note: The validator.xml defines specific validations which apply to form beans.

validation-rules.xml

<!DOCTYPE form-validation PUBLIC"-//Apache Software Foundation//DTD Commons Validator Rules Configuration1.1.3//EN"

I. Creating a project

II. Creating anApplicationResource.propertiesfile.

III. Implementing a registrationpage.

IV. Setting up the database andcreating the a table for registeredusers.

V. Creating the user class

VI. Configuring Hibernate

VII. Adding Struts, Hibernate andSpring libraries

VIII. Configuring Spring

IX. Validation

COMMUNITIES ARTICLES BLOGS RESOURCES DOWNLOADS HELP

LOG ON | |EMBARCADERO HOME ENGLISHLOCATION

Share This

Watch, Follow, & Connect with Us

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 1/12

Page 2: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

# Struts Validator Error Messageserrors.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.

Note: Starting in Struts 1.2.0 the default javascript definitions havebeen consolidated to commons-validator. The default can be overriddenby supplying a <javascript> element with a CDATA section, just asin struts 1.1.

-->

<form-validation>

<global>

<validator name="required"classname="org.apache.struts.validator.FieldChecks"method="validateRequired"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"msg="errors.required"/>

<validator name="requiredif"classname="org.apache.struts.validator.FieldChecks"method="validateRequiredIf"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,org.apache.commons.validator.Validator,javax.servlet.http.HttpServletRequest"msg="errors.required"/>

<validator name="validwhen"msg="errors.required"classname="org.apache.struts.validator.validwhen.ValidWhen"method="validateValidWhen"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,org.apache.commons.validator.Validator,javax.servlet.http.HttpServletRequest"/>

<validator name="minlength"classname="org.apache.struts.validator.FieldChecks"method="validateMinLength"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.minlength"jsFunction="org.apache.commons.validator.javascript.validateMinLength"/>

<validator name="maxlength"classname="org.apache.struts.validator.FieldChecks"method="validateMaxLength"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.maxlength"jsFunction="org.apache.commons.validator.javascript.validateMaxLength"/>

<validator name="mask"classname="org.apache.struts.validator.FieldChecks"method="validateMask"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.invalid"/>

<validator name="byte"classname="org.apache.struts.validator.FieldChecks"method="validateByte"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.byte"jsFunctionName="ByteValidations"/>

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 2/12

Page 3: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

jsFunctionName="IntegerValidations"/>

<validator name="long"classname="org.apache.struts.validator.FieldChecks"method="validateLong"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.long"/>

<validator name="float"classname="org.apache.struts.validator.FieldChecks"method="validateFloat"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.float"jsFunctionName="FloatValidations"/>

<validator name="double"classname="org.apache.struts.validator.FieldChecks"method="validateDouble"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.double"/>

<validator name="date"classname="org.apache.struts.validator.FieldChecks"method="validateDate"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.date"jsFunctionName="DateValidations"/>

<validator name="intRange"classname="org.apache.struts.validator.FieldChecks"method="validateIntRange"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends="integer"msg="errors.range"/>

<validator name="floatRange"classname="org.apache.struts.validator.FieldChecks"method="validateFloatRange"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends="float"msg="errors.range"/>

<validator name="creditCard"classname="org.apache.struts.validator.FieldChecks"method="validateCreditCard"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.creditcard"/>

<validator name="email"classname="org.apache.struts.validator.FieldChecks"method="validateEmail"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.email"/>

<validator name="url"classname="org.apache.struts.validator.FieldChecks"method="validateUrl"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"depends=""msg="errors.url"/>

<!--

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 3/12

Page 4: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"><display-name>StrutsTutorial</display-name><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><taglib><taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri><taglib-location>/WEB-INF/struts-logic.tld</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/struts-tiles.tld</taglib-uri><taglib-location>/WEB-INF/struts-tiles.tld</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/struts-nested.tld</taglib-uri><taglib-location>/WEB-INF/struts-nested.tld</taglib-location></taglib></jsp-config><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><init-param><param-name>debug</param-name><param-value>2</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></web-app>

Note: The web.xml provides general deployment and configuration information for web applications.

II. Creating an ApplicationResource.properties file.Before moving on, let create and populate an ApplicationResources.property file. This file does not go in the WEB-INF folder, butinstead goes in the root of your source tree. The information below is also included at the top of the validator-rules.xml, except forthe last lines (in bold).

ApplicationResources.properties

# Struts Validator Error Messageserrors.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.

errors.passwords.different=Passwords do not match.errors.email.found=E-mail address is already registered.

label.email=E-maillabel.password=Passwordlabel.verify_password=Verify password

This file is used to store all String literals that are used in your application. Why is this useful? If you always use this file, you willalways know exactly where you need to go if you need to modify or add a String. Let's say your application has 60 JSPs. It would bea pain to have to modify a common error message in each and every JSP in your application, rather than simply modifying a singleerror message text in the ApplicationResources.properties file. In addition, this file can be extended to support different languageseasily. Basically what you would do is have a bunch of copies of this file all named slightly differently to designate each particularregion (e.g. ApplicationResources_es.properties for Spanish), and then you would translate the value parts of the name/value pairsinto the particular language.

ApplicationResources_es.properties:

# Struts Validator Error Messageserrors.required={0} se requiere.<etc.>

(Note: I may have butchered the grammer for how this error would be presented in Spanish -- this is just an looseexample)

Note: In this tutorial, we will be making changes only to the struts-config.xml and validator.xml files. Thisvalidator-rules.xml already has all of the validation rules defined, so there will be no reason to make anychanges to this file. We will talk more about validation and its purpose in Struts web applications later. Theweb.xml should not require any additional modification (for this tutorial), although you should make sure thatthe value in the <display-name> element matches the name of your web application.

III. Implementing a registration page.

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 4/12

Page 5: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

<tr><td><html:submit value="Submit" property="Submit"/></td></tr></table></html:form></body></html:html>

Now let's review the Struts related contents and make sense of the various tags we have referenced.

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

The above is our reference to the struts-html.tld tag library that we placed in our WEB-INF directory.In this case, it will allow us to create Struts forms to capture user input.

<html:html>

The above is used to render an <html> element with appropriate language attributes if there is acurrent Locale available in the user's session. This is not actually required in order to successfully runthe JSP, but it is free and easy, so why not always use it?

<html:errors/>

This is a quick and dirty way to display any validation errors. We will improve on it later.

<html:form action="registerAction.do">

The above tag represents an input form which is associated with a bean whose propertiescorrespond to the various fields of the form. Note: the bean in this case will be called'RegisterAction(.java)', but our reference is called 'registerAction.do', which is an action mapping thatwe will define in the struts-config.xml. The struts-config.xml will provide all of the mapping andconfiguration information which will ultimately allow our action class (RegisterAction) to receive theform input information from the user to perform validation and database manipulation.

<html:text property="email"/><html:password property="password"/><html:password property="verify_password"/>

The above tags provide actual input fields on the JSP page. The <html:password...> tag is used tohide the password text while the user types the value into the input field. We provide a'verify_password' input field in order to help the user make sure that they do not make any mistakeswhen typing in the value into the field. Later, we will use the action class we create to perform asimple custom validation method which will help us compare the 'password' with the 'verify_password'to make sure that they match.

<html:submit value="Submit" property="Submit"/>

This final tag provides a button which the user clicks when they are ready to submit the informationwithin the form.

B. Creating the registeration action classHere is our basic RegisterAction class. It will not do anything yet, except return the user to the registration page

package com.tutorial.struts.action;

import org.apache.struts.action.ActionMapping;import org.apache.struts.action.ActionForm;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.ActionForward;import org.apache.struts.action.Action;

public class RegisterAction extends Action{

public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response){String forward = "register";// todo: Fill in the logic to be able to read, validate, and store the form data.return mapping.findForward(forward);}

}

C. Updating the struts-config.xml with a form-beans and action-mappings elementsHere is an updated struts-config.xml with the action mapping for the RegisterAction class. It also has a section thatdefines our form bean, which holds the values which are submitted from the registration JSP. We will go over bothsections in detail below:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD StrutsConfiguration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">

<struts-config>

<form-beans> <form-bean name="registerActionForm"type="org.apache.struts.validator.DynaValidatorActionForm"><form-property name="email" type="java.lang.String" /><form-property name="password" type="java.lang.String" /><form-property name="verify_password" type="java.lang.String" /></form-bean></form-beans>

<action-mappings> <action input="/register.jsp" name="registerActionForm"path="/registerAction" scope="session"type="com.tutorial.struts.action.RegisterAction" validate="yes"><forward name="register" path="/register.jsp" /><forward name="login" path="/login.jsp" /></action> </action-mappings>

<message-resources parameter="ApplicationResources" /><plug-in className="org.apache.struts.validator.ValidatorPlugIn"><set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" /></plug-in></struts-config>

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 5/12

Page 6: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

path="/registerAction"

?

scope="session"

This whole registration process should be considered a single session, so weindicate above that the scope is per session.

type="com.tutorial.struts.action.RegisterAction"

The type relates directly to the name of our action class using full packagedelineation.

validate="yes"

The validate element turns on validation for our action. We will discuss validation inmore detail below.

<forward name="register" path="/register.jsp" /><forward name="login" path="/login.jsp" />

These two forward elements handle two possible results from a form submission:success or failure. If the registration 'successful' then the user is sent to the 'login'page (which we will create later), or if the registration 'fails', we send the userback to the registration page to resolve any registration problems.

Now let's review the form beans section:

<form-beans> ... </form-beans>

All form-bean elements will be defined between the form-beans element above.

<form-bean name="registerActionForm"type="org.apache.struts.validator.DynaValidatorActionForm"><form-property name="email" type="java.lang.String" /><form-property name="password" type="java.lang.String" /><form-property name="vpassword" type="java.lang.String" /></form-bean>

The form-bean element has a name (remember that the 'name' here matches the 'name' in theaction mapping), and a type. For the type we have two choices. Either we could define a beanwith a set of properties that relate to the fields in our registration JSP (e.g. create a class thathas three String properties for email, password, and verify password with getters and settersfor each), or we can do as we have done above and use an existing helper class to provide thisfor us. We use the DynaValidatorActionForm, because it provides us with standard validationfor free. We define the properties for that ActionForm class right in the xml as form-properties. Ifyou do not need to provide custom form beans, using this helper class can reduce code clutter,and make the project easier to maintain.

At this point, let's test to make sure that everything is 'working' as it should. To do this simply compile the project andthen place a breakpoint on the return statement in RegisterAction.java. If you are using JBuilder, simply right-click on theregister.jsp and choose 'WebDebug'. If you are not using an IDE, simply build the WAR and test that it runs inthe webserver without generating any exceptions. When the JSP loads, just click the 'Submit' button -- the execution should stopat the breakpoint. If you continue, you should be able to go back to the register.jsp and click submit again to repeat.Once you have verified that the application runs successfully, continue below.

IV. Setting up the database and creating the a table for registered users.Note: You can use basically any database you want, but this tutorial assumes the use of MySQL for thebackend. If you use another database, you will need to substitute vender-specific values in the appropriateplaces.

The first step is to download, install and start the MySQL Server. Next, download the MySQL JDBC driver. Once the server is installedand running, use the MySQL console to create a database named 'tutorial'. Here are the steps to do this:

1. Open a console and navigate to .../MySQLServer/bin2. Run mysql.exe3. Enter the following commands in the mysql console:

mysql>CREATE DATABASE tutorial;mysql>exit

Once the database is created, you will need to create a table to hold the registration records which are submitted from ourregistration process.

Using JBuilder, complete the following steps to configure the IDE with the MySQL JDBC driver:

1. Enterprise | Enterprise Setup | Database Drivers | Add...2. New... | Type 'MySQL' for the name, set the location to be 'User Home' | Add...3. Navigate to the location of the MySQL JDBC driver and select it (e.g. .../mysql-connector-java-3.1.13-

bin.jar).4. OK | OK | OK5. Choose File | Save All (just in case you have not already)6. Exit and restart JBuilder

Now, take a moment to configure the project for MySQL:

1. Project | Project Properties | Paths | Required Libraries2. Add... | select the 'MySQL' from the 'User Home' section3. OK | OK

Next, we use the Database Pilot to configure a connection to the MySQL server. This allows us to test theconnection and later to add and modify tables using the GUI, or by SQL directly.:

1. Tools | Database Pilot2. View | Options... | Drivers | and verify that 'com.mysql.jdbc.Driver' appears in the 'Drivers" listbox. If

it doesn't, click Add... | and enter 'com.mysql.jdbc.Driver' in the 'Driver class' dialog. | OK | OK3. File | New... | select 'com.mysql.jdbc.Driver' from the Driver combobox | and paste in the following for

the URL: jdbc:mysql://localhost/tutorial | OK4. File | Apply (if available)

Finally, we open the connection we just created to create our 'users' table.

1. Double-click the 'mysql://localhost/tutorial' in the treeview under 'Database URLs' in the DatabasePilot

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 6/12

Page 7: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

package com.tutorial.beans;

public class User{private long id;private String email;private String password;

void User() { }public void setId(long id) { this.id = id; }public long getId() { return id; }public String getEmail() { return email; }public String getPassword() { return password; }public void setEmail(String email) { this.email = email; }public void setPassword(String password) { this.password = password; }public String toString() { return ""; }public boolean equals(Object o) { return false; }public int hashCode() { return 0; }}

VI. Configuring HibernateThe main configuration for Hibernate is located within the hibernate.cfg.xml, which should be located in the root of the source tree. Ifthis file has not been created, create it now, and paste in the following information:

hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate ConfigurationDTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><!-- This (Hibernate) xml file defines Hibernate properties and JDBC connectioninformation, as well as the mapping xml files --><hibernate-configuration><session-factory><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost/tutorial</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password"></property><property name="hibernate.connection.pool_size">10</property><property name="show_sql">true</property><property name="dialect">org.hibernate.dialect.MySQLDialect</property><property name="hibernate.hbm2ddl.auto">update</property><propertyname="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property><property name="hibernate.cache.use_query_cache">true</property><!-- Set this to make batch updates larger: --><property name="hibernate.jdbc.batch_size">20</property><property name="hibernate.cglib.use_reflection_optimizer">true</property><!-- Mapping files --><mapping resource="user.hbm.xml"/></session-factory></hibernate-configuration>

You may wonder, how does our hibernate.cfg.xml get read in by our application? The answer is through implementation of ahibernate plug-in class. A default class can be used, but it is often useful to have access to a custom implementation.We shall use thefollowing simple implementation:

HibernatePlugin.java:

package com.codesoup.archangel.hibernate;

import java.net.URL;import javax.servlet.ServletException;

import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.struts.action.ActionServlet;import org.apache.struts.action.PlugIn;import org.apache.struts.config.ModuleConfig;import org.hibernate.cfg.*;import org.hibernate.*;

public class HibernatePlugin implements PlugIn{private Configuration config;private SessionFactory factory;private String path = "/hibernate.cfg.xml";private static Class hpclass = HibernatePlugin.class;public static final String KEY_NAME = hpclass.getName();private static Log log = LogFactory.getLog(hpclass);

public void setPath(String path) { this.path = path; }

public void init(ActionServlet servlet, ModuleConfig modConfig) throws ServletException{try{URL url = HibernatePlugin.class.getResource(path);config = new Configuration().configure(url);factory = config.buildSessionFactory();servlet.getServletContext().setAttribute(KEY_NAME, factory);}catch (MappingException e){log.error("Mapping errors:", e);String[] messages = e.getMessages();for (int i = 0; i < messages.length; i++)log.error(messages[i], e);throw new ServletException();}catch (HibernateException e){log.error("Hibernate errors:", e);String[] errors = e.getMessages();for (int i = 0; i < errors.length; i++)log.error(errors[i], e);

throw new ServletException();}}

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 7/12

Page 8: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

</form-bean></form-beans><action-mappings><action input="/register1.jsp" name="registerActionForm" path="/registerAction" scope="session"type="com.tutorial.struts.action.RegisterAction" validate="yes"><forward name="register" path="/register1.jsp" /><forward name="login" path="/login.jsp" /></action></action-mappings><message-resources parameter="ApplicationResources" /><plug-in className="org.apache.struts.validator.ValidatorPlugIn"><set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" /></plug-in><plug-in className="com.tutorial.hibernate.HibernatePlugin"><set-property property="path" value="/hibernate.cfg.xml" /></plug-in></struts-config>

Now, let us create the file which Hibernate uses to map the properties in the user class to the corresponding columns in thedatabase. This file will also be placed in the root of the source folder.

user.hbm.xml:

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- This (Hibernate) xml file maps all of the properties in the User class to the coorespondingcolumns in the database --><hibernate-mapping><class name="com.tutorial.beans.User" table="users"><id name="id" type="long" column="id" ><generator class="increment"/></id><property name="email"><column name="email"/></property><property name="password"><column name="password"/></property></class></hibernate-mapping>

In order to make the xml files [or other file types] appear in JBuilder (within the Project Pane), open Project Properties |Build | Resource | scroll down and select 'xml' | and select the 'Copy' radio button | OK. Double-clicking on the file in theProject Pane will open it in the Editor.

VII. Adding Struts, Hibernate and Spring librariesFor development purposes, it is a good idea to add all required libraries and their dependancies to the classpath, even if they arecurrently not explicitly needed by your application. Look in the extracted download directory for each of the third-party frameworksand add references to all of the necessary JARs. How will you know exactly what to add? Well, the first rule is more is better thanless. Take Hibernate for example, there should be a hibernate3.jar sitting in the main Hibernate folder, so make sure to grab that.Then you will need all of the libraries that hibernate3.jar depends on. Luckly they provide all of those in the .../hibernate/lib folder, sograb all of those files as well.

At this point, it would be a good idea to take a moment to compile and perform a test run of the application. If all of the pieces are inplace, and all of the required libraries are available, the project should work without throwing any exceptions.

Later we will work on adding custom code to our RegisterAction class to make it use the values submitted by the client using the webform to perform custom validation, and then if all goes well, post the new registeree through a database transaction using Spring.

Troubleshooting:Issue:

You receive the following message either during compilation, or later when Tomcat is starting up:

log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax).

Solution:

There are at least two ways:

a. If you want to modify Tomcat in general to resolve this issue (this will affect all webapps running inTomcat):

The solution is the following:

Place both log4j.jar and the Jakarta commons-logging.jar here:

$TOMCAT_HOME/common/lib directory.

Next, create your log4j properties file here:

$TOMCAT_HOME/common/classes/log4j.properties

b. If you want to resolve this issue only for your particular application (e.g. if you are using Tomcat insideJBuilder):

The solution is the following:

Make sure that a version of log4j.jar and the Jakarta commons-logging.jar are onyour classpath:

Next, place a log4j properties file in the root of your source tree.

Here is a sample log4j.properties file, which you can use right away. Note that the log4j.rootLogger is set todebug. This will help you troubleshoot subtle problems immediately, though you may wich to change thisvalue to info, once your application is working and stable.

### standard log4j.properties file to control logging output ###

### direct log messages to stdout ###log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target=System.outlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p%c{1}:%L - %m%n

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 8/12

Page 9: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

#log4j.logger.org.hibernate.cache=info

### log transaction activity#log4j.logger.org.hibernate.transaction=debug

### log JDBC resource acquisition#log4j.logger.org.hibernate.jdbc=debug

### enable the following line if you want to track down connection ###### leakages when using DriverManagerConnectionProvider ####log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

Issue:

If you run your application in JBuilder and receive the following log message [Note:you must enable logging to see this message -- see above]:

07:53:32,637 ERROR HibernatePlugin:36 - Mapping errors:org.hibernate.MappingException: Could not read mappings from resource:user.hbm.xml

Solution:

After compiling your project, look in your module directory for your User class (e.g..../<StrutsTutorial>/<WEB-INF>/classes/com/tutorial/beans/User.class). If youdon't see it, then in JBuilder right-click on your web module | Properties | Content |and uncheck 'Only include module specific Java classes'. Then just recompile yourproject and retest.

VIII. Configuring SpringThe first thing you will need to create is an xml file that will provide a definition to allow Spring to create a User bean for us. These xml file allow usto define a simple and consistent way of creating a namespace of JavaBeans objects which will be managed by a Spring BeanFactory. This ishandy because then it is quite easy to save our new user into the database (i.e. no SQL needed).

So, create the following file in the root of your source tree:

user.xml:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><!-- This (Spring) xml file defines the bean used with the Spring bean factory object --><beans><bean id="user" class="com.tutorial.beans.User"></bean></beans>

Now let's take a look at an updated version of our RegisterAction.java class, which is provided in its entirty below:

RegisterAction.java:

package com.tutorial.struts.action;

import javax.servlet.http.*;import org.apache.commons.logging.*;import org.apache.commons.validator.*;import org.apache.struts.*;import org.apache.struts.action.*;import org.apache.struts.validator.*;import org.hibernate.*;import org.hibernate.criterion.*;import org.springframework.beans.factory.*;import org.springframework.beans.factory.xml.*;import org.springframework.core.io.*;import com.tutorial.beans.*;import com.tutorial.hibernate.*;

public class RegisterAction extends Action{

private static Class thisClass = RegisterAction.class;private static Log log = LogFactory.getLog(thisClass);

/*Method checks to see if password and verify password match, if not return false*/private boolean isValidPassword(HttpServletRequest request, String password, Stringverify_password){

boolean valid = false;if (password.matches(verify_password)) { valid = true; }return valid;

}

/*Method checks database for email and returns false if it already exists*/private boolean isUniqueEmail(Session session, HttpServletRequest request, String email){

boolean result = true; // assume that it isCriteria criteria = session.createCriteria(User.class);criteria.add(Expression.eq("email", email));criteria.setMaxResults(1);User duplicate = (User)criteria.uniqueResult();if (duplicate != null){

if (duplicate.getEmail().matches(email)){

result = false; // set to false when we find the same emailin the database

}

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 9/12

Page 10: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

}

/*** Save the specified error messages keys into the appropriate request* attribute for use by the <html:errors> tag, if any messages* are required. Otherwise, ensure that the request attribute is not* created.** @param request The servlet request we are processing* @param errors Error messages object*/protected void saveErrors(HttpServletRequest request, ActionMessages errors){

// Remove any error messages attribute if none are requiredif ((errors == null) || errors.isEmpty()){

request.removeAttribute(Globals.ERROR_KEY);return;

}// Save the error messages we needrequest.setAttribute(Globals.ERROR_KEY, errors);

}

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequestrequest, HttpServletResponse response){

String forward = "register";SessionFactory sessionFactory = (SessionFactory)servlet.getServletContext().getAttribute(HibernatePlugin.KEY_NAME);Session session = sessionFactory.openSession();DynaValidatorActionForm dform = (DynaValidatorActionForm) form;ActionMessages errors = dform.validate(mapping, request);if (errors.isEmpty()){

try{

if (!isValidPassword(request, (String)dform.get("password"), (String)dform.get("verify_password"))){

errors.add(Globals.ERROR_KEY, newActionMessage("errors.passwords.different"));

}else if (!isUniqueEmail(session, request, (String)dform.get("email"))){

errors.add(Globals.ERROR_KEY, newActionMessage("errors.email.found"));

}else{

registerUser(session, request, dform);forward = "success";

}

}catch (Exception e) { e.printStackTrace(); }finally{

session.flush();session.close();

}

}saveErrors(request, errors);return mapping.findForward(forward);

}

}

Let's look at a few methods in this class:

RegisterAction.execute(...):

This method first creates a Hibernate session using the plug-in class we provided. The sessionobject is what we will use to create custom queries against the database. Next, we create aDynaValidatorActionForm class and cast the ActionForm object that is passed into this methodinto it. Then we use the DynaValidatorActionForm to create an instance of our ActionMessagesclass, which we use to keep track of any validation errors. We check to see if there are anyerrors already existing and if so, we forward the user back to the register page to resolvethose problems. If there are no errors, then we need to perform two other customervalidations before we register this new user by adding them to the database. The first thing weneed to check is if the 'password' field matches the 'validate_password' field, we do this withisValidPassword(...). If it not valid, we add an error message 'errors.passwords.different' thatrefers back to the ApplicationResources.properties. So if the password was valid, we thencheck to make sure that the submitted email is unique (i.e. there should never be two userswith the same e-mail) by calling isUniqueEmail(...). If it is not a unique e-mail, then we add an

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 10/12

Page 11: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

Now, at this point, you should be able to run the application, open the register.jsp in a browser, add and e-mail address, password, (matching)verify password and click 'submit' to add the row to the users table in the database. If you have a way to view the database data directly, youshould see a new row with your submitted information.

In JBuilder, you can open the Database Pilot to view the row you added (Tools | Database Pilot | expand'mysql://localhost/tutorial' | expand 'Tables' | expand 'users' | and click on the 'Data' tab.

IX. ValidationI promised earlier to return to the subject of validation, so here we go. Nearly all of the elements are in place to start implementing validation, wejust need to provide a more detailed validation.xml. Lets look at an updated version:

validation.xml:

<?xml version="1.0" encoding="ISO-8859-1" ?><!DOCTYPE form-validation PUBLIC"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN""http://jakarta.apache.org/commons/dtds/validator_1_0.dtd"><form-validation><formset><form name="/registerAction"><fieldproperty="email"depends="required,email"><arg0 key="label.email"/></field><fieldproperty="password"depends="required,minlength,maxlength"><arg0 key="label.password"/><arg1name="minlength"key="${var:minlength}"resource="false"/><var><var-name>minlength</var-name><var-value>8</var-value></var><arg2name="maxlength"key="${var:maxlength}"resource="false"/><var><var-name>maxlength</var-name><var-value>36</var-value></var></field><fieldproperty="verify_password"depends="required,minlength,maxlength"><arg0 key="label.verify_password"/><arg1name="minlength"key="${var:minlength}"resource="false"/><var><var-name>minlength</var-name><var-value>8</var-value></var><arg2name="maxlength"key="${var:maxlength}"resource="false"/><var><var-name>maxlength</var-name><var-value>36</var-value></var></field></form></formset></form-validation>

Let's look at this file in more detail:

<form-validation><formset>

<form name="/registerAction">

...

</form>

</formset></form-validation>

The above form tag (in bold) indicates which JSP form is being validated. You can add more form tags underthe formset tag as you create new actions.

<fieldproperty="email"depends="required,email"><arg0 key="label.email"/></field>

The above field tag is used to describe how the e-mail field should be validated. The depends attribute listswhich particular rules found in the validator-rules.xml should be enforced for this field. In this case, we seethat required and email rules are used. Let take a moment and examine the relevant part of the associatedvalidator-rules.xml:

<validator name="required"classname="org.apache.struts.validator.FieldChecks"method="validateRequired"methodParams="java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionMessages,javax.servlet.http.HttpServletRequest"msg="errors.required"/>

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 11/12

Page 12: Struts, Hibernate and Spring_ a Guide to Creating a Dynamic Web Application

Copyright© 1994 - 2010 Embarcadero Technologies, Inc. All rights reserved. Site Map

<arg2name="maxlength"key="${var:maxlength}"resource="false"/><var><var-name>maxlength</var-name><var-value>36</var-value></var></field>

I did not mention the arg0 attribute in the last discussion of email, so lets talk about it now. Thearg0 attribute replaces the {0} found in the ApplicationResources.properties file under the textvalues for errors.required, errors.minlength, and errors.maxlength with the text value underlabel.password. That sounds more complicated that it really is. Really we just want to find a wayto be able to resource all our strings (including validation error messages) back to theApplicationResources.properties file (or a region specific one). When you see an arg1, or arg2attribute, then these would replace a {1} or {2} respectively, and so on.

Remember how we used the following in our register.jsp as a quick and dirty way to display validation errors?

<html:errors/>

Well, now we have a chance to improve on it. Replace the above with what is shown below:

<%-- Improved error display --%><logic:messagesPresent><ul class="error"><html:messages id="error"><li style="color: red;"><bean:write name="error"/></li></html:messages></ul></logic:messagesPresent>

You may be asking, why take something that was simple and do the same thing in a more complicated way? Well, the above will allow us morecontrol over the display of the errors (e.g. carriage returns and color).

Now when you run this application, you should get errors displayed in red when you submit the form without having the fields correct filled out.

Now that validation has been introduced, this tutorial should provide enough information to get you started working with Struts, Spring andHibernate. This concludes this tutorial.

Move mouse over comment to see the full text

Server Response from: ETNASC03

LATEST COMMENTS

2/8/2011 Struts, Hibernate and Spring: A guide t…

edn.embarcadero.com/article/36524?b… 12/12