|
Recipe 6.1. Creating a Base ActionProblemYou want to implement and enforce a common feature or behavior across all of your Actions. SolutionImplement an abstract base class that incorporates the behavior in its execute( ) method. As shown by the class in Example 6-1, the execute( ) method calls abstract methods that are implemented by subclasses. Example 6-1. Abstract base actionpackage com.oreilly.strutsckbk.ch06; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public abstract class BaseAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { executeBefore( ); // call the abstract method ActionForward forward = executeAction( mapping, form, request, response ); executeAfter( ); return forward; } protected abstract ActionForward executeAction( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception; private void executeBefore( ) { //Real stuff goes here } private void executeAfter( ) { //Real stuff goes here } protected CommonServices getCommonServices( ) {...} } DiscussionFor some applications, you may want to apply global business rules any time a user accesses the application, submits a form, or clicks on a link. Here are some common examples of these rules:
You can enforce these across-the-board features using an abstract base Action class that your custom Actions extend. The Solution above shows such a base Action. BaseAction extends org.apache.struts.action.Action and implements the standard execute( ) method. The execute() method calls the private method executeBefore( ) and then the abstract method executeAction(). executeAction( ) returns an ActionForward, which is stored in a local variable. Next, the private method executeAfter( ) is called. The execute( ) method ends by returning the ActionForward referenced by the local variable. Your concrete actions extend this BaseAction. Each concrete action implements the executeAction( ) method as if it were the execute( ) method inherited from org.apache.struts.action.Action. If you are familiar with design patterns, you will probably recognize the Solution as the Template Method from Design Patterns of Object-Oriented Software by Erich Gamma, et al. (Addison-Wesley). The Template Method pattern is characterized by a base abstract class that defines the steps of an algorithm. In the Solution, the steps are comprised of a pre-execution step, the execution step, and a post-execution step. If you want subclasses to be able to override the common behavior in the pre- and post-execution steps, make the methods protected; otherwise, they should be private. The signature of the executeAction( ) method is identical to the execute( ) method; however, this is not required. In general, you'll want to pass through at least the set of parameters available to the execute( ) method. In addition, you may want to pass additional references to objects that are created in the base class, such as a user object representing the current user. Base actions can provide access to global objects and services that concrete actions will need. For example, you might want to provide a getUser( ) method that returns a user object for the current session. Chapter 11 provides more detail on this specific case. See AlsoChuck Cavaness discusses the use of a base Action class in Programming Jakarta Struts (O'Reilly). The timeless book Design Patterns of Object-Oriented Software by Erich Gamma, et al. (Addison-Wesley) is the bible of design patterns. In its pages is an assortment of low-level design approaches applicable to any object-oriented application. |
|