Sunteți pe pagina 1din 20

Error validation and exception handling in portlets,

using the Struts Portlet Framework

Rajender Sriramoju
Portal Architect
November, 2004

© Copyright International Business Machines Corporation 2004. All rights reserved.

Error validation and exception handling are important aspects in Web applications.
Having a good design and implementation for error validation and exception handling
makes applications more robust and allows them to gracefully respond in abnormal
conditions.

This article tells how you can leverage the error validation and exception handling
features, which are built into the WebSphere Portal Struts Portlet Framework, in your
portlet applications. A sample Registration application, which accompanies this article as
a download, illustrates the use of these features.
Table of contents

Introduction ......................................................................................................................... 2
About the examples............................................................................................................. 3
Error validation in Struts portlets ........................................................................................ 3
Programmatic error validations....................................................................................... 3
ActionForm as a data collector and buffer ...................................................................... 4
Action firewall – Validates data before the action sees it ............................................... 4
Creating the Struts portlet application................................................................................. 5
JSPs ................................................................................................................................. 6
Classes............................................................................................................................. 6
Resources ........................................................................................................................ 6
Step 1: Create a Struts Portlet project. ............................................................................ 6
Step 2: Create an ActionForm class. ............................................................................... 8
Step 3: Specifiy error messages. ................................................................................... 11
Step 4: Create custom validations. ................................................................................ 11
Step 5: Create and configure an Action class................................................................ 13
Step 6: Run the application. .......................................................................................... 14
Reporting business layer errors to the user ....................................................................... 16
Struts exception handling .................................................................................................. 18
Conclusion......................................................................................................................... 19
Resources .......................................................................................................................... 19
Download .......................................................................................................................... 19
About the author................................................................................................................ 19

Introduction
Most portlet applications accept input from users. For example, the input might come in
a form consisting of input text fields, dropdown lists, radio buttons, or check boxes.
However, the user input does not always make sense. An application might expect
specific date and phone number formats, require certain input fields, and need other
specific forms of data. Therefore, the application needs to validate the input.

Where possible, perform all input validations at the presentation service layer, and
display useful and meaningful error messages so that the user can supply missing
information, or correct invalid data items. Also, display meaningful and useful error
messages when system outages occur, or or when critical business rule validation failures
happen at the business and data service layers.

For example, when a user tries to update or add data records to a backend database
through a portlet, there may be several validations that take place in various modules in
the business and data layers of the system. If any of the validations fails, you need to
display an appropriate error message. If you provide structured error messages with an
error number, you improve customer service and application reliability.
Websphere Portal V5.0 provides the Struts Portlet Framework, which supports
deployment of Struts applications as portlets. You can leverage the error validation and
exception handling features which are built into this framework.

This article describes options for server side error validation and exception handling in
Struts-based portlets.

This article assumes that you have basic knowledge of the IBM Portlet API, Struts, and
J2EE development using Websphere Studio.

About the examples


This article includes a sample application as a download. The example code is for a
portlet called Registration, which shows you how to implement error validations in a
Struts portlet. You can install and run this.

The following products were used to develop and deploy the example application.

• IBM® Websphere® Studio Application Developer V5.1.2 (hereafter called


Application Developer)
• IBM Portal Toolkit 5.0.2.2
• IBM Websphere Portal V5.0.2.1

Error validation in Struts portlets


The Struts framework is a popular way of implementing the presentation services layer of
portlet applications based on Websphere Portal. This section discusses the various
options available within the Struts framework for error validation design and
implementation in Struts portlets. For more information on developing Struts applications,
and on migrating Struts applications to WebSphere Portal, see the Resources section.

Using Struts framework, you can implement error validation in two ways:

1. Programmatically, using ActionForm and including custom validation in validate()


method.

2. Declaratively, by enabling configurable error validations using the Struts Validator


Framework.

Programmatic error validations


When a user submits an HTML form, your application could be faced with the tedious
task of retrieving request parameters, performing validations and displaying appropriate
error messages. This kind of functionality is performed in various places in Web
applications; it should be handled at the framework level and be reusable across
applications. The Struts framework relies on the ActionForm class as the key component
for handling these kinds of tasks.
ActionForm as a data collector and buffer
Because users often enter invalid data, Web applications need a way to store the input
data temporarily so that it can be redisplayed when an error occurs. You can use the
ActionForm class is to collect input data from an HTML form and transfer it to Action
class. In this sense, the ActionForm class acts as a buffer to hold the state of data which
the user entered while it is being validated.

Figure 1 illustrates the life cycle of input processed using the ActionForm.

Action firewall – Validates data before the action sees it


ActionForm acts as a traffic cop. If validation is turned on for an action, the action will
not be executed unless the ActionForm’s validate() method says the ActionForm is
valid.

The following activity diagram illustrates the life cycle of the Struts ActionForm class. It
shows the steps involved in the ActionForm error validation process when a user enters
input values into a form and submits it.
Figure 1. Life cycle of an ActionForm

Creating the Struts portlet application


The Registration portlet application, included with the download, enables a new user
to register to access an application. It implements the error validation using the
ActionForm:validate() method.

The Registration application applies these error validation rules:


• All input fields on the registration form are required.
• If a user does not complete all fields, an error message displays at the top of the form.
• If the password and re-enter password fields do not match, an error message displays.

The Registration application includes the following components.


JSPs
• Registration.jsp: Displays Registration view and allows you to enter the user
registration information in a form. If any validation errors occur, they will be
displayed at the top of form on registration.jsp page
• Confirm.jsp: This page gets displayed upon successful execution of Registration
action

Classes
• ActionForm: RegistrationForm.java
Extends ActionForm and includes the custom form validation
• Action: RegistrationAction.java
Extends Action class and executes upon successful form validation and forwards to
confirm.jsp

Resources
• Resources File: ApplicationResources.properties file that includes all error
messages appropriate to the application

Now you see how to implement error validation in a Struts portlet application.

Step 1: Create a Struts Portlet project.


In Application Developer:

1. Select New -> Project, and create a Portlet project. Creates the registration JSP in the
WebContent folder. In the JSP, create an HTML form, within this tag, with the
required fields.
<html:form action="registration"> </html:form>

2. In order to use the Struts html tag, include the tag libraries at the top of JSP.
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

3. When error validations are performed, if any error messages are present, you can
display them by coding the <html:errors/> tag.
Listing 1. Sample JSP. All Input fields are removed from this listing except the first
name field.

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


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

<html:html locale="true">
<head>
<html:base />
<title>Struts Portlet Error Validation Example1</title>
<link rel="stylesheet" href="<%=
response.encodeURL("/stylesheet/sample.css") %>" type="text/css">
</head>

<body topmargin="0" leftmargin="5" marginheight="0" marginwidth="0" >


<html:form action="registration">

<table border="0" cellpadding="0" cellspacing="0">


<tr class="fieldlabel">
<td class="error"><html:errors /></td>
</tr>
<tr class="fieldlabel">
<td height="10"></td>
</tr>
<tr class="fieldlabel">
<td>All fields required</td>
</tr>
<tr class="fieldlabel">
<td height="10"></td>
</tr>
<tr class="fieldlabel">
<td>First Name</td>
</tr>
<tr>
<td><html:text property="firstName" size="30"
maxlength="30" />
</td>
</tr>
</table>
</html:form>
</body>
</html:html>
Step 2: Create an ActionForm class.
In Application Developer:

1. Select FileÆNewÆOtherÆWebÆStrutsÆActionForm Class.

2. Click Next, provide a name for the action form, and choose a package. For example,
the sample application uses RegistrationForm in the
com.demo.struts.registration.form package.
3. Select the validate(…,HttpServletRequest) method.
4. Click Next, so you can choose the form fields from the registration.jsp page. The
ActionForm is created from the form fields of JSP. Choose the appropriate fields and
click Next.
You see all the form fields you selected displays as new fields for the ActionForm
Class.

5. Click Next and check Add new mapping.


6. For the Configuration File Name, use WEB-INF/struts-config.xml.
7. Enter a form bean name (for example, RegistrationForm) and click Finish.

Application Developer creates the action form, and adds an entry in the Struts
configuration file (struts-Config.xml) form-beans tag.
<!-- Form Beans -->
<form-beans>
<form-bean name="registrationForm"
type="com.demo.struts.registration.form.RegistrationForm">
</form-bean>
</form-beans>

If you look at RegistrationForm, you see that get and set methods are created for
each field chosen for the form.

Now you are ready to include the custom validations in your action form’s validate()
method.

Step 3: Specifiy error messages.


Before you code the validate()method in the ActionForm, make sure you have the
necessary information about the validations that you need to perform, including the
appropriate error messages for each validation. Include the message id and corresponding
error message in the ApplicationResource property file.

# Error Messages
global.error.registration.groupno=<li>Invalid Group Number. Specify a
valid Group Number</li>
global.error.registration.error=<li>Invalid registration</li>
global.error.registration.passworderror=<li>Password and Reenter
Password does not match</li>

global.error.registration.requiredfield=<li>The {0} is required for New


Registration</li>

Step 4: Create custom validations.


Include your custom validations in the validate() method.

In the listing below, you see several of the validations. See RegistrationForm.java
class, in the download, for the entire source.
public ActionErrors validate(ActionMapping mapping,HttpServletRequest
request)
{
ActionErrors errors = new ActionErrors();
if ((firstName == null) || (firstName.length() == 0)) {
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError(
"global.error.registration.requiredfield",
"First Name"));

if ((password == null) || (password.length() == 0))


{
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError(
"global.error.registration.requiredfield",
"Password"));
}

if ((reentryPassword == null) || (reentryPassword.length() == 0))


{
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError(
"global.error.registration.requiredfield",
"Reenter Password"));
}

if (((password != null) && (password.length() > 0))


&& ((reentryPassword != null) &&
(reentryPassword.length() > 0)))
{
if (!password.equalsIgnoreCase(reentryPassword))
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("global.error.registration.passworderror"));
}

return errors;

The validate() method checks the user input, determines if a field is null, and displays
an appropriate message.

The validate()method returns the ActionErrors object. The ActionErrors class


encapsulates one or more errors that have been found by the application. Each error
occurrence is represented by an instance of org.apache.struts.action.ActionError.

The ActionErrors object has a request scope. After an instance is created and populated
by the validate() method, it is stored into the request. A JSP can retrieve the object
from the request and iterate through ActionError objects to display the error messages
to the user.
You can create the instance of ActionErrors in the validate()method . As you find
errors, you can add the ActionError object to the ActionErrors object. In a JSP, you
retrieve the errors using the <html:errors /> tag.

To choose an error message for a form field, you can use any of the several constructors
of the ActionError class. Below are some examples.

• new ActionError("global.error.registration.requiredfield",
"Password"))
global.error.registration.requiredfield=<li>The {0} is required for
New Registration</li>

The first string argument corresponds to a key from the application’s resource bundle.
The remaining arguments are used as parametric replacement values for the error
message.
• new ActionError("global.error.registration.groupno"))
The first key argument retrieves the corresponding error message from the application
resource bundle.
global.error.registration.groupno=<li>Invalid Group Number. Specify
a valid Group Number</li>

• If all the errors are to be displayed at the top of the page, you can use the constant
ActionErrors.GLOBAL_ERROR
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("global.error.registration.passworderror"))

Step 5: Create and configure an Action class.

If the validation is enabled for an action class in the struts-config.xml file, then the
ActionForm associated with the action class validate() method runs. If all the
validation conditions succeed in the ActionForm class validate() method, then the
execute()method of the Action class is called.

Important: Make sure to set the Action mapping validation flag to true in the struts-
config.xml so that the Struts framework runs the specified ActionForm’s validate()
method.
<action
path="/registration"
type="com.demo.struts.registration.action.RegistrationAction"
scope="request"
name="registrationForm"
validate="true"
input="/registration.jsp" >
<forward name="success" path="/confirm.jsp" redirect="true"/>
<forward name="failure" path="/registration.jsp"
redirect="true"/>
</action>
You can use the Action class execute() method to call business layer commands and
services. If any remote exceptions or business layer validation errors occur, then you can
use the ActionErrors class to report the errors to the JSP.

Step 6: Run the application.


1. Before running the application, modify the web.xml file to set a welcome page. In
this sample application, you should set the welcome page to registration.jsp.

<welcome-file-list>
<welcome-file>registration.jsp</welcome-file>
</welcome-file-list>

2. Set up the WebSphere Portal server test environment using the Server perspective.
3. Right-click on the portlet application project, and choose Run on server. The
registration page launches.

4. Without entering any test data,click Register. Error messages display at the top of the
form.
5. Enter different values for Password and Reenter Password fields; you can see does
not match error message at the top of form.
6. Enter appropriate data. When all the form fields pass through the validations,
RegistrationAction class runs the execute() method and forwards control to
confirm.jsp.

The above sample application illustrated the design and implementation of error
validations in a Struts portlet.

Reporting business layer errors to the user


How do you report business service layer or remote exceptions to the end user? For
example, in the sample appliction, the group number and company entered by the user
must match with the backend database. If there is a mismatch, you can report it to the
user.

Let’s examine the flow of this application and how it reports the business layer errors to
an end user. (See also the Figure1. Lifecycle of an ActionForm.)

1. User submits data through form of registration.jsp.


<html:form action="registration">

2. The RegistrationForm associated with RegistrationAction is populated with


HTML form fields, and the validate() method executes.
3. When all the validations are completed, control passes to the RegistrationAction
class, and the execute() method is called.

The RegistrationAction class creates a Java bean that can be passed to the
business layer.
RegistrationForm registrationForm = (RegistrationForm) form;
RegistrationBean regBean = new RegistrationBean();

// Create a business layer bean regBean by populating from


RegistrationForm
BeanUtils.copyProperties(regBean, registrationForm);

The RegistrationAction class invokes a business command object, instead of


directly calling business layer objects.
RegistrationCommand regCommand = new RegistrationCommand();
boolean regFlag = regCommand.registerUser(regBean);

4. RegistrationCommand invokes RegistrationService and passes the bean object.


public boolean registerUser(RegistrationBean regBean) throws
RegistrationException
{
RegistrationService regService = new RegistrationService();
try {
regFlag = regService.registerUser(regBean);
} catch (RegistrationException re) {
throw new RegistrationException("Registration failed..
thrown in command...");
}
return regFlag;
}
5. RegistrationService performs business validations. In a real application, the
service can call a data access object to retrieve data from a back end system, such as a
database, legacy system, or Web service.
public boolean registerUser(RegistrationBean regBean) throws
RegistrationException
{
String groupNo = regBean.getGroupNo();
String companyName = regBean.getCompanyName();

System.out.println("Group Number.."+ groupNo +


"Company Name..."+ companyName);

if (groupNo.equalsIgnoreCase("GP12345") &&
companyName.equalsIgnoreCase("MyCompany"))
{
// here you can code to access a DAO and get data from backend
return true;
}
else
{
throw new RegistrationException("Registration failed..A
valid group no and company required");
}
}

• If validations pass through in the registerUser(RegistrationBean regBean)


method, it returns a true value; otherwise, the method throws
RegistrationException.
• RegistrationCommand catches the RegistrationException and throws it.
• RegistrationAction class catches the RegistrationException, creates a new
ActionError object, and adds it to the ActionErrors object.
• Depending on the error type, Action class forwards the ActionError object to the
appropriate JSP.

try {
BeanUtils.copyProperties(regBean, registrationForm);
RegistrationCommand regCommand = new RegistrationCommand();

boolean regFlag = regCommand.registerUser(regBean);

if (regFlag = true)
forward = mapping.findForward("success");
} catch (RegistrationException re) {
errors.add( ActionErrors.GLOBAL_ERROR,
new ActionError("global.error.registration.error"));
saveErrors(request, errors);
return mapping.findForward("failure");
} catch (Exception e) {
e.printStackTrace();
errors.add( ActionErrors.GLOBAL_ERROR,
new ActionError("global.error.systemfailure.error"));
saveErrors(request, errors);
return mapping.findForward("failure");
}
Struts exception handling
Struts Framework V1.1 provides an exception handling framework for the applications. It
enables developers to declare exceptions using the struts-config.xml file. You can
modify the exception handling logic without recompiling the code.

In the struts-config.xml file, you can specify the exceptions that could occur and the
action to take if they do occur, both at the global level and for a specific action mapping.

This code shows how to specify a global level action.

<global-exceptions>
<exception
key="global.error.registration.error"
path="/registration.jsp"
scope="request"

type="com.demo.struts.registration.exceptions.RegistrationException"
/>
</global-exceptions>

This code shows how to specify an action mapping level exception.


<action
path="/registration"
type="com.demo.struts.registration.action.RegistrationAction"
scope="request"
name="registrationForm"
validate="true"
input="/registration.jsp" >
<forward name="success" path="/confirm.jsp" redirect="true"/>
<forward name="failure" path="/registration.jsp"
redirect="true"/>
<exception
key="global.error.registration.error"
path="/registration.jsp"
type="com.demo.struts.registration.exceptions.RegistrationException"/>
</action>

The exception element of the Action class in the struts-config.xml file specifies the
path to the page to be forwarded when one of the specified exceptions occurs during an
action invocation. Whenever an exception is not handled programmatically (that is, is is
not caught in the try-catch block in the action class execute() method), then
wpsRequestProcessor gets a chance to check if there is a specific exception element
configured. If there is one specified, control is passed to the resource specified in the path
attribute of the exception element.
Conclusion
This article described an approach to designing and implementing error validation and
exception handling in Struts based portlets, using a sample Registration application.

Resources
• Writing a Simple Struts Application using WebSphere Studio V5
http://www.ibm.com/developerworks/websphere/techjournal/0302_fung/fung.html
• Migrating a Struts application to Websphere Portal
http://www.ibm.com/developerworks/websphere/techjournal/0403_yu/0403_yu.html
• Build error-free apps fast: Manage beans and error validation in WebSphere Portal
and Java Server Faces
http://www.ibm.com/developerworks/edu/i-dw-wes-jsfportals-i.html
• Struts User’s Guide
http://struts.apache.org/userGuide/index.html
• Programming Jakarta Struts, 2nd Edition, by Chuck Cavaness
O’Reilly & Associates, 2004. ISBN 0596006519
• Portlet Development guide
http://www.redbooks.ibm.com/abstracts/sg246076.html?Open
• Portal Application design and development guidelines
http://www.redbooks.ibm.com/abstracts/redp3829.html?Open
• Websphere Portal Information Center – Portlet development
http://www.ibm.com/developerworks/websphere/zones/portal/proddoc.html
• developerworks Websphere Studio zone
http://www.ibm.com/developerworks/websphere/zones/studio/
• IBM Websphere Portal Toolkit
http://www.ibm.com/websphere/portal/toolkit
• developerworks Websphere Portal zone
http://www.ibm.com/developerworks/websphere/zones/portal/

Download
To get the error handling example code that accompanies this article see:
http://www.ibm.com/developerworks/websphere/library/techarticles/0411_sriramoju/041
1_sriramoju.html

About the author


Rajender Sriramoju works as a WebSphere Portal architect. He has worked
with IBM Websphere Portal server since V4.0, and he has an extensive
background in architecture, design, development, and implementation of
large scale J2EE and portal applications. He works primarily on portal
architecture, design, and integration with various enterprise systems. When
he is not working, Rajender listens to Bluegrass and country music, and
plays guitar. You can reach Rajender at mailto:rajender@sbcglobal.net.
Trademarks

• DB2, IBM, Lotus, Tivoli, Rational, and WebSphere are trademarks or registered
trademarks of IBM Corporation in the United States, other countries, or both.
• Windows and Windows NT are registered trademarks of Microsoft Corporation in the
United States, other countries, or both.
• Java and all Java-based trademarks and logos are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States, other countries, or both.
• Other company, product, and service names may be trademarks or service marks of
others.

IBM copyright and trademark information: http://www.ibm.com/legal/copytrade.phtml

S-ar putea să vă placă și