Struts, an open source framework you can use to build Web applications, is based on the popular Model-View-Controller (MVC2) design paradigm. The framework is built upon standard technologies like Java Servlets, JavaBeans, ResourceBundles, and XML, and it provides flexible and extensible components. Struts implements the Controller layer in the form of ActionServlet and recommends building the View layer using JSP tag libraries. Struts also provides a wrapper around the Model layer through Action classes. Figure 1 illustrates the Struts framework based on the Model-View-Controller design.
Figure 1. Struts and MVC
First, we'll explain the Struts components in the context of best practices and the role each one plays in your Web application development.
Every Action of your application extends Struts' org.apache.struts.action.Action. These Action classes provide an interface to the application's Model layer, acting as a wrapper around the business logic. Each Action class must provide its case-specific implementation to the perform() method. The perform() method always returns a value of type ActionForward.
Every ActionForm of your application extends Struts' org.apache.struts.action.ActionForm. ActionForms are simple JavaBeans that encapsulate and validate request parameters. To validate your request data, your ActionForm's validate() method must give a case-specific implementation. ActionForms serve as a carrier of request data to the Action class. A JSP object combines with a respective ActionForm to form your application's View layer, where almost every form field of the JSP object maps to an attribute of the corresponding ActionForm.
The JSP custom tag libraries are a collection of actions presented as tags. This is a powerful feature of the JSP Specification 1.1; it allows you to separate presentation from other application tiers. The libraries are easy to use and you can read them in XML-like fashion. You can easily maintain the JSP components by minimizing the use of Java scriptlets in them. The JSP tags that Struts provides include HTML, logic, and bean tags.
You use ActionErrors to support exception handling. An ActionError traps and propagates an application exception to the View layer. Each one is a collection of ActionError instances. ActionErrors encapsulate error messages, while the </html:errors> in the Presentation layer renders all error messages in the ActionError collection.
Best Practice 1. Reuse data across multiple ActionForms
Now that you are familiar with the Struts components, we will continue by showing you ways to get the most out of the framework. First, Struts recommends that you associate every JSP object with an ActionForm, which encapsulates data represented in the screen. You access the form data in the JSP object using accessory methods found in ActionForm. Listing 1 shows the conventional use of ActionForm tag in the View layer.
Listing 1. Using ActionForm in JSP
<html:form action="/bp1"> <html:text property="attrib1" /> </html:form > |
The ActionForm called "BP1AForm" includes the attribute attrib1, as well as its getter and setter methods. In the configuration file struts-config.xml, the action "/bp1" maps to bp1AForm using the name attribute. This facilitates data display in the JSP.
To implement this best practice, Struts recommends you do two things:
- Create a JavaBean (
BP1BForm) with attributes that form an attribute subset inBP1AForm, along with the attributes' getter and setter methods. - Replace the attributes in
BP1AFormwith the beanBP1BFormby associating the bean withBP1AForm. Now you can access this attribute subset inBP1AFormthroughBP1BForm. Listing 2 shows you how.
Listing 2. Accessing form attributes in JSP
<html:form action="/bp1">
<bean:define name="bp1AForm" property="bp1BForm" id="bp1B"
type="com.ibm.dw.webarch.struts.BP1BForm" />
<html:text name="bp1B" property="subsetAtt1" />
</html:form >
|
This practice's main advantage is that you can use it when you need multiple ActionForms to access a set of attributes. When following this best practice, you'll want to keep in mind the following:
- Struts implements the
<bean:define/>tag. - When the code
<%@ taglib uri="struts-bean.tld" prefix="bean" %>points tostruts-bean.tld, the<bean:define/>tag starts to work in the JSP components. BP1AForm's validation framework, which extendsActionForm, must validateBP1BForm's data.
When creating Action classes in your application, instead of directly extending org.apache.struts.action.Action, create an Action class (IntermediateAction) by extending org.apache.struts.action.Action to handle common things in your application. All other Action classes extend this IntermediateAction class.
Best Practice 2. Use Action class to handle requests
Typically when using the Struts framework, for every action the JSP component requests your application to execute, the application must extend Struts' org.apache.struts.action.Action to create an Action class. This individual Action class interfaces with the application's Model layer while processing the request.
To implement this practice, Struts recommends you follow these steps:
- Create an
Actionclass, sayBP2Action, by extendingorg.apache.struts.action.Action. - Create all other
Actionclasses in your Web application by extendingBP2Action. - In
BP2Action, create a methodperformTask(), as in public abstractActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException. - In
BP2Actionadd one or more generic methods to the application, for exampleserverSideValidate(). You can decide on the method's access modifier by considering the following factors:- If all
Actionclasses must implement this method, make it abstract. - If some
Actionclasses will provide a case-specific implementation, declare the method protected and give it a default implementation.
- If all
- In
BP2Action, declare methodperform()as final. Invoke the above generic method, which must always be called before processing the request. Now call the methodperformTask()created in step 3. - In every
Actionclass extendingBP2Action, add methodperformTask()with a case-specific implementation.
This practice has two main advantages. First, it helps you avoid redundant code in every Action class of your Web application. Second, it gives the application more control over generic tasks by centralizing the behavior in one Action class.
Best Practice 3. Use ActionForm to work on session data
In a Struts-based Web application, each ActionForm extends org.apache.struts.action.ActionForm. These ActionForms encapsulate page data and provide a validation framework to validate request parameters.
Most Web applications maintain data in session to make them available throughout the application. This best practice addresses this Web application feature. It allows methods toSession() and fromSession() to move session data to and from the form data. Thus, it addresses session data maintenance in a Web application.
To adhere to this practice, follow these steps:
- Create an abstract class named
BP3Formby extendingorg.apache.struts.action.ActionForm. - In
BP3Form, add methods with access modifiers as in public abstractvoid toSession(SessionData sessionData)andvoid fromSession(SessionData sessionData). - In every
ActionForm, extendBP3Formand implement the abstract methods in which the form data is transported to and from the session. - The corresponding
Actionclass may determine the order in which these methods are called. For example, you could invoke methodtoSession()on theActionFormjust beforeactionForwardis determined.
This practice is most useful when session data is maintained as a single object and/or every page manipulates or uses session data.
Best Practice 4. Handle exceptions effectively
Conventionally, when an application exception occurs in an Action class, the exception is first logged. Then the class creates an ActionError and stores it in the appropriate scope. This Action class then forwards control to the appropriate ActionForward. Listing 3 shows how Action class handles exceptions.
Listing 3. Exception handling in an Action class
try {
//Code in Action class
}
catch (ApplicationException e) {
//log exception
ActionErrors actionErrors = new ActionErrors();
ActionError actionError = new ActionError(e.getErrorCode());
actionErrors.add(ActionErrors.GLOBAL_ERROR, actionError);
saveErrors(request, actionErrors);
}
|
While conventional exception handling procedures save exception information in every Action class, best practice 4 aims to avoid redundant code while handling exceptions.
To use this practice, Struts recommends following these steps:
- Create an
Actionclass, sayBP4Action, by extendingorg.apache.struts.action.Action. - Create all other
Actionclasses in your Web application by extendingBP4Action. - In
BP4Action, declare variableActionErrors actionErrors = new ActionErrors();. - In
BP4Action, create a methodperformTask()as in public abstractActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionErrors actionErrors) throws IOException, ServletException. - In
BP4Action, declare methodperform()as final. Then invoke generic methods, which must always be called before processing the request. Now you can call the methodperformTask()created in the previous step. - While implementing method
performTask()in everyActionclass (by extendingBP4Action), handle application exceptions as shown in Listing 4.
Listing 4. Using ActionErrors effectively
try {
//Code in Action class
}
catch(ApplicationException appException) {
//Log exception
//Add error to actionErrors
actionErrors.add(ActionErrors.GLOBAL_ERROR,
new ActionError(appException.getErrorCode()));
} |
In BP4Action, after invoking the method performTask(), save the ActionErrors using saveErrors(request, errors).
This practice's main advantage is that it avoids code redundancy in every Action class that handles ActionErrors.
Building an easily maintainable Web application can be one of the most challenging tasks for a development team. Using a mature framework like Struts helps you implement the infrastructure code normally associated with building an application. The Struts framework provides a set of standard interfaces for plugging business logic into the application, a consistent mechanism across development teams for performing tasks such as user data validation, screen navigation, and so forth, as well as a set of custom tag libraries to simplify developing screens.
These four best practices are important for you to extract more from the framework's features. You, as a developer, can benefit from these lessons to increase your code modularity and application reusability, plus minimize code redundancy. These are all critical to building an extensible Web application.
- Find out more about Struts at the Jakarta Struts Home page.
- Download the Struts source code.
- Read "Struts, An Open-Source MVC Implementation" for an introduction to Struts (developerWorks, February 2001).
- Discover the "Struts Adoption" discussion of pertinent Struts issues.
- Explore a useful reference on Struts, Mastering Jakarta Struts by James Goodwill (Wiley Publishers, 2002).
- Read about changes to Struts, including the Tiles library in "Struts and tiles aid component-based development" (developerWorks, June 2002).
- Browse for books on these and other technical topics.
- Visit developerWorks Web Architecture and Java technology zones for a range of articles on the topics of Web architecture, usability, and Java.
Palaniyappan Thiagarajan specializes in Web application development using Struts framework and IBM JADE framework. He has presented topics on the Struts framework in technical forums, and holds professional certifications from IBM in IBM WebSphere Application Server 3.5, IBM DB2 Family Fundamentals and IBM Certification for OOAD and UML. He has also written articles for IBM developerWorks, Java zone.

Pagadala Suresh specializes in Java technology, WebSphere Application Server, and WebSphere Studio Application Developer (WSAD), Ariba Buyer. He has participated in the IBM Redbook program on WebSphere, and has professional experience in WebSphere Business Components Composer and IBM JADE Framework.




