ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

A Look at Commons Chain, Part 2
Pages: 1, 2, 3, 4

The ComposableRequestProcessor overrides the process method so that it can run the chain (that is, execute the command):


public void process(HttpServletRequest request,
                        HttpServletResponse response)
        throws IOException, ServletException {

    // Wrap the request in the case of a multipart request
    request = processMultipart(request);
        
    // Create and populate a Context for this request
    ActionContext context = contextInstance(request, response);

    // Create and execute the command.
    try {
        command.execute(context);
    } catch (Exception e) {
        // Execute the exception processing chain??
        throw new ServletException(e);
    }

    // Release the context.
    context.release();
}

Where did all the steps go? An XML configuration file, chain-config.xml, defines the sequence of commands to execute. (The exception here is the processMultipart method. This method, implemented in the ComposableRequestProcessor, wraps the request if its content type is multipart/form-data). Let's dig into the chain-config.xml file to see how it works. First, Struts takes advantage of Commons Chain support for sub-chains, which can represent entire chain as a command, using the LookupCommand. The define element is used as a convenience mechanism for defining sub-chains using the LookupCommand.


<define name= "lookup"
   className="org.apache.commons.chain.generic.LookupCommand"/>

The ComposableRequestProcessor executes the chain named servlet-standard. This chain is composed of three commands:

servlet-exception A Chain filter for handling exceptions. A filter is a special command that implements a postprocess method. The postprocess method of the filter is called after every command in the chain (actually, its after every command that follows the filter's declaration).
process-action The main sequence for processing the request and executing the appropriate action.
process-view Handles forwarding to the view (e.g., a JSP page).


<chain name="servlet-standard">

    <!-- Establish exception handling filter -->
    <command
          className="org.apache.struts.chain.commands.ExceptionCatcher"
        catalogName="struts"
   exceptionCommand="servlet-exception"/>

    <lookup
        catalogName="struts"
               name="process-action"
           optional="false"/>

    <lookup
        catalogName="struts"
               name="process-view"
           optional="false"/>

</chain>

The process-action chain defines the commands for processing the request and calling your actions.


<chain name="process-action">
  <lookup catalogName="struts"
                 name="servlet-standard-preprocess"
             optional="true"/>

  <command className=
    "org.apache.struts.chain.commands.servlet.SelectLocale"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.RequestNoCache"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.SetContentType"
  />        
  <command className=
    "org.apache.struts.chain.commands.servlet.SelectAction"
  />
  <command className= 
    "org.apache.struts.chain.commands.servlet.AuthorizeAction"
  />    
  <command className=
    "org.apache.struts.chain.commands.servlet.CreateActionForm"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.PopulateActionForm"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.ValidateActionForm"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.SelectInput"
  />
  <command className=
    "org.apache.struts.chain.commands.ExecuteCommand"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.SelectForward"
  />
  <command className=
    "org.apache.struts.chain.commands.SelectInclude"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.PerformInclude"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.CreateAction"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.ExecuteAction"
  />
</chain>

The processFoo methods of the original RequestProcessor have been re-implemented as classes that implement the Chain Command interface. In Struts, each Command implementation extends from an abstract base class. This base class implements the execute method of the Command interface. The execute method then calls methods of the concrete class that perform the actual work.

Consider how the locale is retrieved from the HTTP request and stored. First, here's implementation of processLocale from the original RequestProcessor:


protected void processLocale(HttpServletRequest request,
                             HttpServletResponse response) {

    // Are we configured to select the Locale automatically?
    if (!moduleConfig.getControllerConfig().getLocale()) {
        return;
    }

    // Has a Locale already been selected?
    HttpSession session = request.getSession();
    if (session.getAttribute(Globals.LOCALE_KEY) != null) {
        return;
    }

    // Use the Locale returned by the servlet container (if any)
    Locale locale = request.getLocale();
    if (locale != null) {
        session.setAttribute(Globals.LOCALE_KEY, locale);
    }
}

The new chain implementation processes the locale using two classes, AbstractSelectLocale and SelectLocale. The abstract class implements the execute method:


public boolean execute(Context context) throws Exception {
    ActionContext actionCtx = (ActionContext) context;

    // Are we configured to select Locale automatically?
    ModuleConfig moduleConfig = actionCtx.getModuleConfig();
    if (!moduleConfig.getControllerConfig().getLocale()) {
        return (false);
    }

    // Retrieve and cache appropriate Locale for this request
    Locale locale = getLocale(actionCtx);
    actionCtx.setLocale(locale);

    return (false);
}

SelectLocale extends AbstractSelectLocale and implements the abstract getLocale method:


protected Locale getLocale(ActionContext context) {

    ServletActionContext saContext = (ServletActionContext) context;

    // Has a Locale already been selected?
    HttpSession session = saContext.getRequest().getSession();
    Locale locale = (Locale) session.getAttribute(Globals.LOCALE_KEY);
    if (locale != null) {
        return (locale);
    }

    // Select and cache the Locale to be used
    locale = saContext.getRequest().getLocale();
    if (locale == null) {
        locale = Locale.getDefault();
    }
    session.setAttribute(Globals.LOCALE_KEY, locale);
    return (locale);

}

Pages: 1, 2, 3, 4

Next Pagearrow