Chapter 10: Effectively Extending Struts


In this chapter:

  1. You will learn how to extend Struts using PlugIn as an example

  2. You will see how to construct a rudimentary page flow controller by customizing ActionMapping

  3. You will develop a mechanism for controlling validation for image button form submission

  4. You will see how to handle sensitive resubmissions in a generic way rather than handling in every form

  5. You will devise a strategy to avail DispatchAction-like functionality for image button form submission

Struts is a generic framework. It works fine without modification. But there are times when it has to be customized. And we are not talking about straightforward customizations like extending the Form, Action and custom tags. We are referring to the ‚“hooks ‚½ that Struts provides to extend the framework. In this chapter you will see several practical uses of these hooks.

A word of caution though: The customization features are probably going to be around without modification until Struts 2.0. The main candidates for overhaul are ActionMapping and RequestProcessor . The replacements would be designed using Command, interceptor and chain of responsibility patterns. However, since the above classes is part of public API, an alternative strategy will definitely emerge to seamlessly migrate the customizations discussed in this chapter so that none of the application code is affected and only the customization code might change. Of course this is just a speculation.

To understand the hooks, consider a Struts Plugin for say, a slick menu utility (Such a utility indeed exists. Check out http://struts-menu. sourceforge .net). The menu utility needs to read the configuration data from an external file. If the PlugIn were instead implemented as a servlet, it would read the file name from an < init-param > in web.xml . The < set-property > can do the same task for the PlugIn. The file name is set in the struts-config.xml by using < set-property >.

 <plug-in className="mybank.example.MyMenuPlugIn">              <set-property  property="fileName"  value="/WEB-INF/menudata.xml"/>         </plug-in> 

A JavaBeans property with the same name ( fileName ) is then added to the PlugIn class. The < set-property > tells the Struts framework to set the corresponding JavaBeans property in the plugin class (or any class associated with the configuration) with the value attribute of the < set-property > element. In addition, the Struts PlugIn implements the PlugIn interface from org.apache.struts.action package. Accordingly, the MyMenuPlugIn class is defined as:

 public class MyMenuPlugIn implements PlugIn {           private String fileName;  public String getFileName() {   return fileName;   }   public void setFileName(String name) {   this.fileName = name;   }    public void init(ActionServlet servlet,                ModuleConfig config) throws ServletException {   .. ..   }   public void destroy() {   .. ..   }   } 

During startup, Struts sets the fileName property using the corresponding setter method (and other properties if exist) and finally calls the init() method. Since PlugIns are the last ones to be configured by Struts, all other data from the struts-config.xml is guaranteed to be loaded before the init() method is invoked. The init() method is an opportunity to override and change any other settings including the RequestProcessor! Frameworks like SAIF (stands for Struts Action Invocation Framework. Available at http://struts.sourceforge.net) utilize this to change the RequestProcessor to one of its own.

Back to < set-property >. The < set-property > is the cornerstone of hook-based customization. Its DTD entry is as follows :

 <!ATTLIST set-property   id        ID        #IMPLIED                          property  CDATA     #REQUIRED                          value     CDATA     #REQUIRED> 

Both property and value are mandatory and ID is never set explicitly. The following elements in struts-config.xml can be customized using < set-property >: Form-bean, Exception, DataSource, PlugIn, RequestProcessor, MessageResources, ActionForward and ActionMapping.

Customizing the action mapping

The < action mapping > is the most frequently customized element. One way to customize action mapping is by setting the className in struts-config.xml as shown in Listing 10.1.

Listing 10.1: struts-config.xml for custom action mapping
 <action   path="/submitCustomerForm"               className=  "mybank.struts.MyActionMapping"  type="mybank.app1.CustomerAction"               name="CustomerForm"               scope="request"               validate="true"               input="CustomerDetails.jsp">   <  set-property property="buttons"   value="nextButton,saveButton,cancelButton" /  >   <  set-property property="forwards"   value="page2,success,cancel" /  >       <forward name="page2"  path="Page2.jsp"  />       <forward name="success"  path="success.jsp"  />       <forward name="success"  path="cancel.jsp"  />     </action> 
 

The className attribute tells Struts to use the specified class ( mybank.struts.MyActionMapping ) for storing the action-mapping configuration. MyActionMapping extends ActionMapping in the package org.apache.struts.action. In addition it has a JavaBeans property for each of the < set-property > elements. MyActionMapping class is shown below:

 public class MyActionMapping extends ActionMapping {        private String buttons;        private String forwards;        //getters and setters for actions and forwards        public MyActionMapping() { }     } 

The custom action mapping is now ready to use. During startup, Struts instantiates the subclass of ActionMapping (instead of ActionMapping itself) and sets its JavaBeans properties to the values specified in the corresponding < set-property > element. As you know, the execute() method in the Action accepts ActionMapping as one of the arguments. When the execute() method in the CustomerAction is invoked at runtime, MyActionMapping is passed as the ActionMapping argument due to the setting in Listing 10.1. It can then be cast to MyActionMapping to access its JavaBeans properties as follows:

 public ActionForward execute(ActionMapping mapping,             ActionForm form, HttpServletRequest request,             HttpServletResponse response) throws Exception {         MyActionMapping customMapping =                              (MyActionMapping) mapping;         String actions = customMapping.getButtons();           ..         ..      } 

There are several uses of simple customizations like this. As you will see later in this chapter, a lot of code that needs to be often repeated everywhere can be eliminated by simple customizations. While doing so, a single customized ActionMapping will be used for all the action mappings in the application. Setting the className for individual action mapping as shown in Listing 10.1 is painful. The alternative is to specify the type attribute on the < action-mappings > element as shown in Listing 10.2. This tells Struts to use the corresponding ActionMapping class for all the < action > elements. Listing 10.2 forms the basis for some of the utilities we develop in this chapter ‚ a rudimentary page flow controller, auto-validation feature for image based form submissions, a generic mechanism to handle sensitive form resubmissions and a DispatchAction-like facility for image based form submissions. All of these will use the base Action class and base form conceived in Chapter 4 in conjunction with the HtmlButton described in Chapter 6 for form submission.

Listing 10.2: struts-config.xml with global custom action mapping
 <action-mappings  type="mybank.struts.MyActionMapping"  >     <action   path="/submitCustomerForm"               type="mybank.app1.CustomerAction"               name="CustomerForm"               scope="request"               validate="true"               input="CustomerDetails.jsp">   <  set-property property="buttons"   value="nextButton,saveButton,cancelButton" /  >   <  set-property property="forwards"   value="page2,success,cancel" /  >       <forward name="page2"  path="Page2.jsp"  />       <forward name="success"  path="success.jsp"  />       <forward name="success"  path="cancel.jsp"  />     </action>     </action-mappings> 
 



Struts Survival Guide. Basics to Best Practices
Struts Survival Guide: Basics to Best Practices (J2ee Survival Series)
ISBN: 0974848808
EAN: 2147483647
Year: 2004
Pages: 96

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net