Section 3: Processing Requests with Action Objects

The Basic Struts Flow of Control

3.1 The Six Basic Steps 3.2 Example 1: One Result Mapping
3.3 Example 2: Multiple Result Mappings 3.4 Source Code
Struts Tutorial Table of Contents More Info

This section describes the steps involved in creating a bare-bones Struts application, and gives examples that illustrate these steps. The applications shown in this section are stripped-down versions that use only the minimum necessary Struts capabilities. The next few sections illustrate more complete applications.

3.1 The Six Basic Steps in Using Struts

With Struts, the normal processing flow is that a form submits data to a URL of the form blah.do. That address is mapped by struts-config.xml to an Action object, whose execute method handles the request. One of the arguments to execute is a form bean that is automatically created and whose properties are automatically populated with the incoming form data. The Action object then invokes business logic and data-access logic, placing the results in normal beans stored in request, session, or application scope. The Action uses mapping.findForward to return a condition, and the conditions are mapped by struts-config.xml to various JSP pages. The system forwards the request to the appropriate JSP page, where the bean:write tag is used to output properties of the form bean and results beans. Optionally, both the input form and the final JSP pages can use bean:message to output standard messages and labels as defined in a system property file.

Here are the minimum steps needed to create an application that follows this process. This section will focus on the basic flow and the Action objects; the next section will show how to use beans.

  1. Modify struts-config.xml.
    Use WEB-INF/struts-config.xml to: Be sure to restart the server after modifying struts-config.xml; the file is read only when the Web application is first loaded.
  2. Define a form bean.
    This bean is a class the extends ActionForm and will represent the data submitted by the user. It is automatically populated when the input form is submitted. Beans will be discussed in the next section.
  3. Create results beans.
    In the MVC architecture, the business-logic and data-access code create the results and the JSP pages present them. To transfer the results from one layer to the other, they are stored in beans. These beans differ from form beans in that they need extend no particular class, and they represent the output of the computational process, not the input to the process. Beans will be discussed in the next section.
  4. Create an Action object to handle requests.
    The struts-config.xml file designates the Action object that handles requests for various URLs. The Action objects themselves need to do the real work: invoke the appropriate business- and data-access-logic, store the results in beans, and designate the type of situation (missing data, database error, success category 1, success category 2, etc.) that is appropriate for the results. The struts-config.xml file then decides which JSP page should apply to that situation.
  5. Create form that invokes blah.do.
    You need to create an input form whose ACTION corresponds to one of the *.do addresses listed in struts-config.xml. At a minimum, the input form should look like this:
    ????
    ...

    However, in Section 5, we will discuss the advantages of using the Struts html:form tag to build this input form.
  6. Display results in JSP.
    Since Struts is built around the MVC architecture, these JSP pages should avoid JSP scripting elements whenever possible. For basic Struts, these JSP pages usually use the Struts bean:write tag, but in JSP 2.0 the JSP 2.0 expression language is a viable alternative. In complex cases, the JSP pages also use the JSP Standard Tag Library (JSTL) or the Struts looping/logic tags.

    In most cases, the JSP pages only make sense when the request is funneled through the Action, since it is the Action that invokes the logic that creates the data that the JSP pages will display. So, the JSP pages are placed in WEB-INF, where RequestDispatcher can forward to them but where clients cannot access them directly. If the JSP pages makes sense independently of the Action (e.g., if they display session data), then the JSP pages should be placed in a regular subdirectory of the Web application, and the forward entries in struts-config.xml should say redirect="true"/>.

3.2 Example 1: One Result Mapping

In this example, the URL http://hostname/struts-test/actions/register1.do should be handled by the class RegisterAction1 (which extends Action and is in the coreservlets package). RegisterAction1 always returns "success", and this return value results in the JSP page /WEB-INF/results/result1.jsp being displayed to the client.


  1. Modify struts-config.xml.
  2. Define a form bean.
  3. Create results beans.
  4. Create an Action object to handle requests.
  5. Create form that invokes blah.do.
  6. Display results in JSP.
  7. Final results for this example.
  8. Design Strategy for URLs.

  1. Modify struts-config.xml.
    Use WEB-INF/struts-config.xml to:
    Here is the resultant struts-config.xml (download the source code here).
    
          
    struts-config.xml
    
    .. >
    
      
        
          
         
      
    
    
  2. Define a form bean.
    Beans are postponed until the next section, so this step is omitted for now.
  3. Create results beans.
    Beans are postponed until the next section, so this step is omitted for now.
  4. Create an Action object to handle requests.
    In general, your Action subclass should:
    For this simple example, the Action will do nothing but return "success". Here is the code (download the source code here).
    
          
    RegisterAction1.java
    package coreservlets;
    
    import javax.servlet.http.*;
    import org.apache.struts.action.*;
    
    public class RegisterAction1 extends Action {
      public ActionForward execute(ActionMapping mapping,
                                   ActionForm form,
                                   HttpServletRequest request,
                                   HttpServletResponse response)
          throws Exception {
        return(mapping.findForward("success"));
      }
    }
    
  5. Create form that invokes blah.do.
    In this case, we need an HTML form that invokes http://hostname/struts-test/actions/register1.do. We place the HTML form in the forms subdirectory and use a relative URL for the ACTION as follows.
    
          
    register1.jsp (Excerpt)
    ..>
    
    New Account Registration
    
    

    New Account Registration

    ACTION="../actions/register1.do" METHOD="POST"> Email address:
    Password:
    The POST method is used because the form contains a password field, and .do must be listed explicitly in the URL even though it is omitted in the action declaration in struts-config.xml. (However, the html:form tag shown in the Section 5 will automatically add .do to the URL.) See this section for a discussion of why it is useful to place the forms in a subdirectory instead of in the top-level Web application directory.
  6. Display results in JSP.
    In general, there can be several possible JSP pages corresponding to the various possible return values of the execute method of the Action. In struts-config.xml, each JSP page is declared in a forward entry within the appropriate action. In this simple case, the only return value is "success", so /WEB-INF/results/result1.jsp is used in all cases. This JSP page displays a simple message, as shown below (download the source code here).
    
          
    result1.jsp
    ..">
    
    Success
    
    

    You have registered successfully.

    (Version 1)
  7. Final Results.
    First, the HTML form is invoked with the URL http://localhost/struts-test/forms/register1.jsp, as follows.


    This form is then filled in and submitted, with the form's ACTION resulting in the URL http://localhost/struts-test/actions/register1.do. This address is mapped by struts-config.xml to the RegisterAction1 class, whose execute method is invoked. This method returns a mapping.findForward with a value of "success", and that value is mapped by struts-config.xml to /WEB-INF/results/result1.jsp, which is the final result displayed to the user. However, since the JSP page is invoked with RequestDispatcher.forward, not response.sendRedirect, the URL displayed to the user is register1.do, not result1.jsp. See the following screen shot.

  8. Design Strategy: URLs.
    There are two basic options for choosing the action and form URLs in this and subsequent examples: using simple paths or using paths with subdirectories.

    Option 1: No Subdirectories Option 2: Subdirectories
    Action path gives a name only:
    ??path="/register1"
    ??...>
    Action path gives a pseudo-directory name:
    ??path="/actions/register1"
    ??...>
    Form placed in top-level Web application directory:
    http://hostname/struts-test
    /register1.jsp
    Form placed in Web application subdirectory:
    http://hostname/struts-test
    /forms/register1.jsp
    Form specifies only blah.do:
    ??ACTION="register1.do"
    ??...>
    Form specifies path with .. or /webAppName/:
    ??ACTION="../actions/register1.do"
    ??...>

    Although the first option is simpler, there are several reasons why I think the second option is preferable:

3.3 Example 2: Multiple Result Mappings

In this example, the URL http://hostname/struts-test/actions/register2.do should be handled by the class RegisterAction2. The execute method of RegisterAction2 returns "success", "bad-address", or "bad-password", and these return values result in the JSP pages /WEB-INF/results/result2.jsp, /WEB-INF/results/bad-address2.jsp, and /WEB-INF/results/bad-password2.jsp, respectively.

The main new feature in this example is the use of multiple forward entries within the action element.

  1. Modify struts-config.xml.
  2. Define a form bean.
  3. Create results beans.
  4. Create an Action object to handle requests.
  5. Create form that invokes blah.do.
  6. Display results in JSP.
  7. Final results for this example.
  1. Modify struts-config.xml.
    Use WEB-INF/struts-config.xml to: Here is the resultant struts-config.xml (download the source code here).
    
          
    struts-config.xml (Excerpt)
    
    .. >
    
      
        ...
        
          
          
          
         
      
    
    
  2. Define a form bean.
    Beans are postponed until the next section, so this step is omitted for now.
  3. Create results beans.
    Beans are postponed until the next section, so this step is omitted for now.
  4. Create an Action object to handle requests.
    This example is similar to the previous one except that there are multiple mapping.findForward entries. We return "bad-address" if the email address is missing, is less then three characters long, or does not contain an "@" sign. We return "bad-password" if the password is missing or is less than six characters long. Otherwise we return "success". In this simple example we use request.getParameter explicitly, but in later examples we let Struts automatically populate a bean from the request data.

    Here is the code (download the source code here).

    
          
    RegisterAction2.java
    package coreservlets;
    
    import javax.servlet.http.*;
    import org.apache.struts.action.*;
    
    public class RegisterAction2 extends Action {
      public ActionForward execute(ActionMapping mapping,
                                   ActionForm form,
                                   HttpServletRequest request,
                                   HttpServletResponse response)
          throws Exception {
        String email = request.getParameter("email");
        String password = request.getParameter("password");
        if ((email == null) ||
            (email.trim().length() return(mapping.findForward("bad-address"));
        } else if ((password == null) ||
                   (password.trim().length() return(mapping.findForward("bad-password"));
        } else {
          return(mapping.findForward("success"));
        }
      }
    }
    
  5. Create form that invokes blah.do.
    In this case, we need an HTML form that invokes http://hostname/struts-test/actions/register2.do. We place the HTML form in the forms subdirectory and use a relative URL for the ACTION as follows.
    
          
    register2.jsp (Excerpt)
    ..>
    
    New Account Registration
    
    

    New Account Registration

    ACTION="../actions/register2.do" METHOD="POST"> Email address:
    Password:
  6. Display results in JSP.
    In this case, we have three possible JSP pages, as shown below (download the source code here).
    
          
    bad-address2.jsp
    ..>
    
    Illegal Email Address
    
    

    Illegal Email Address

    Address must be of the form username@host. Please try again.
    bad-password2.jsp
    ..>
    
    Illegal Password
    
    

    Illegal Password

    Password must contain at least six characters. Please try again.
    result2.jsp
    ..>
    
    Success
    
    

    You have registered successfully.

    (Version 2)
  7. Final Results.
    First, the HTML form is invoked with the URL http://localhost/struts-test/forms/register2.jsp, as follows.


    In the first case, this form is given "Bill Gates" as an email address and is submitted.


    The form's ACTION results in the URL http://localhost/struts-test/actions/register2.do. This address is mapped by struts-config.xml to the RegisterAction2 class, whose execute method is invoked. This method examines the email address, determines it is illegal because it lacks an "@" sign, and returns mapping.findForward with a value of "bad-address". That value is mapped by struts-config.xml to /WEB-INF/results/bad-address2.jsp, which is the final result displayed to the user for this input.


    In the second case, the form is given a legal email address but a password that is only two characters long.


    The form's ACTION results in the URL http://localhost/struts-test/actions/register2.do. This address is mapped by struts-config.xml to the RegisterAction2 class, whose execute method is invoked. This method examines the password, determines it is too short, and returns mapping.findForward with a value of "bad-password". That value is mapped by struts-config.xml to /WEB-INF/results/bad-password2.jsp, which is the final result displayed to the user for this input.


    In the third case, the form is given a legal email address and password. The form's ACTION results in the URL http://localhost/struts-test/actions/register2.do. This address is mapped by struts-config.xml to the RegisterAction2 class, whose execute method is invoked. This method finds no problem with either the email address or the password, so returns mapping.findForward with a value of "success". That value is mapped by struts-config.xml to /WEB-INF/results/result2.jsp, which is the final result displayed to the user for this input.

3.4 Source Code for this Section

The following list gives the source code for all files described in this section, listed in the order that they appear.

To download the code, right-click on the links and choose "Save Target As". Be sure to reproduce the same directory structure as given here. The easiest approach is to download and unjar the entire struts-test WAR file, but this takes some time since this WAR file includes the Struts JAR files, not just the example code.

Next section: Handling Request Parameters with Form Beans

More Information

Servlet, JSP, and Struts Short Courses
Personally developed and taught by the author of Core Servlets & JSP, More Servlets & JSP, and this Jakarta Struts tutorial.
  • Programming with Servlet & JSP Technology. Fast-paced, hands-on course for developers who know Java but have little or no experience with servlets and JSP. Offered Nov 30-Dec 3 in Columbia, MD.
  • Advanced Servlet, JSP, & Struts Programming. Advanced hands-on course for developers with significant previous experience with servlets and JSP. Offered Dec 7-10 in Columbia, MD.
  • Applying Apache Struts. Advanced Struts-only course for those with significant previous JSP and servlet experience.
  • On-site JSP, Servlet, Struts, & JSF Training Courses. Customizable courses taught by Marty at your organization. Choose any combination of topics from Marty's Java, JSP, servlet, Struts, and JSF courses.
Contact Marty
Send email to [email protected] to report errors and omissions in this writeup or inquire about JSP/servlet/Struts training courses.
References
  • Apache Struts home page.
  • Apache Struts documentation.
  • JSP and servlet programming resources.
  • Servlet 2.3 and JSP 1.2 API.
  • Servlet 2.4 API.
  • JSP 2.0 API.
  • JSP, servlet, and Struts training and consulting
Apache Struts Books
  • Struts in Action: Building Web Applications with the Leading Java Framework.
  • Programming Jakarta Struts.
  • Professional Jakarta Struts.
Servlet & JSP Books
  • Core Servlets and JavaServer Pages, Second Edition.
  • Free online version of the First Edition of Core Servlets and JavaServer Pages. In PDF.
  • More Servlets and JavaServer Pages.