Struts Best Practices
Struts University Series
Abstract Struts is a flexible and forgiving framework and works well even when you use it wrong. Here are few practices designed to help keep your application on the “straight and narrow”.
Struts Best Practices Configuration Results Actions Server Pages Unit Testing Security Resources
Configuration Use namespaces to organize your application into logical "modules" or units of work. Place each namespace into it's own struts configuration file Try to keep the Actions classes for the namespace in a common package
Configuration Store the struts configuration for that namespace with the Actions If you are using JSPs, try to name the JSP folder after the Action package. If you using templates, bundle the templates with the Actions. Remember, if the namespace needs to change, you do not need to change packages or JSP folders.
Configuration Within a namespace, reuse names for common concepts.
If each namespace has an entry page, use the same action name in each namespace. For example, each namespace in the Cookbook has an "Open" action.
Configuration Use Exception handlers Local or global as needed Configure a global handler for Throwable
Use global result handlers for common results Error Login
Configuration Define a base class constants for common Result names
CANCEL = “cancel”
Actions Use Action properties to represent all input properties request, cookie, or session, whatever Here, properties include helper objects
Validate all input fields — always on the server-side, and optionally on the clientside.
Actions Consider using Model Driven or POJOs if a business object layer contains most properties Do not use Model Driven if the business objects are not well designed or obtained through factory methods
Actions Use a base ActionForm, including a base DynaActionForm, if needed. Use Prepare or Spring to populate rich controls, like dropdown lists Prepare for data access Spring for static values
Actions Write thread-safe Interceptors. Use a base support Action class.
Extend ActionSupport
Use SessionAware and ApplicationAware to avoid referring to servlet resources directly Factor any non-view logic into facades.
Actions Remove business logic to a business facade that the actions can call. Spring is an excellent way to build a business facade. Actions are a necessary evil. Every line of code in an Action is guilty until proven innocent. Ideally, there should be one line of code that calls the business facade, and every other line of a code in an action should be bound to the framework.
Actions Use static parameters to decorate Actions Use subclasses or method aliases to manage related operations (and multiple buttons) Do not embed business logic in action classes.
Actions Avoid chaining "business" actions.
Bad: MoveAction = CopyAction -> DeleteAction Good: Extend your facade. Not the same as redirecting to an Action to complete a workflow
Unit test actions before trying them in a web application.
Since JUnit is integrated in most IDEs now, there is no excuse.
Actions Use token-session or executeAndWait to guard against multiple submits. Prefer BeanUtils copyValues to move data from Action properties to a business object. Consider using a JavaBean helper to encapsulate data and messages returned from the Model.
Server Pages Use a global error page. Always link to Actions, never to server pages. Use the action attributes tag to avoid embedding Action extension. Use s:url to reference HTML assets. Use s:include to include pages
Server Pages Consider using WebCanoo, HtmlUnit, or HttpUnit to test navigation, as the application is being developed. Use SiteMesh, or the equivalent, to separate application "chrome" from the core utility of the server pages..
Server Pages If an image, or other swatch of markup, is being used by multiple pages, remove it to its own server page and include it where necessary.
Better yet, encapsulate the markup in its own UI tag.
Extend the UI tags as needed.
Server Pages Consider using the message resources for page titles, control labels, and so forth, even if the application is not being localized. It is often useful to seperate the concern of what message to display from the concern of where to display it. Use the XML framework to validate input.
Model Use a business facade. Consider a web system facade for nonStruts operations. Test facades outside of Struts. Do not pass Actions to facade.
Unless it implements another interface.
Use chained exceptions.
Model Prefer Transaction Scripts.
http://c2.com/cgi/wiki?TransactionScript
Avoid exposing Domain Models. http://c2.com/cgi/wiki?DomainModel Hint: Encapsulate in Transaction Script
Use EJBs with care.
http://husted.com/struts/tips/018.html
Model Behind your facade, consider using a data access package.
Hibernate
IBATIS
http://hibernate.org/ http://incubator.apache.org/ibatis/
ObjectRelationalBridge
http://db.apache.org/ojb/
Security Utilize a custom Interceptor to enforce authentication Consider using Acegi or SecurityFilter to implement authentication and authorization
Unit Testing Use JUnit to test business facades and Action classes.
http://www.junit.org/index.htm
Use WebCanoo to test server pages.
http://webtest.canoo.com/
Resources Study underlying technologies OGNL Freemarker Spring SiteMesh Dojo (AJAX)
Resources OGNL
http://www.opensymphony.com/ognl/
FreeMarker
http://freemarker.org/
Spring
http://springframework.org/
SiteMesh
http://www.opensymphony.com/sitemesh/
Resources Dojo (AJAX)
http://dojotoolkit.org/
DisplayTag
http://displaytag.sourceforge.net/
WebCanoo
http://webtest.canoo.com/
JUnit
http://www.JUnit.org/
Resources Apache Struts
http://struts.apache.org/
XWork
http://www.opensymphony.com/xwork/
StrutsCentral
http://www.StrutsCentral.net/
Struts University Series