A Big Piictture
Figure lays out the Struts request-response process in a visual sequence. Let us walk through a description of the request-response. The numbers in parentheses refer to figure 5 where appropriate:
- A client requests a path that matches the Action URI pattern (1).
- The container passes the request to the ActionServlet.
- If this is a modular application, the ActionServlet selects the appropriate module.
- The ActionServlet looks up the mapping for the path.
- If the mapping specifies a form bean, the ActionServlet sees if there is one
already or creates one.
- If a form bean is in play, the ActionServlet resets and populates it from the HTTP
- If the mapping has the validate property set to true, it calls validate on the form
- If it fails, the servlet forwards to the path specified by the input property and this
control flow ends.
- If the mapping specifies an Action type, it is reused if it already exists or
- The Action’s perform or execute method is called and passed the instantiated
form bean (or null).
- The Action may populate the form bean, call business objects, and do whatever
else is needed.
- The Action returns an ActionForward to the ActionServlet.
- If the ActionForward is to another Action URI, we begin again; otherwise, it’s off
to a display page or some other resource. Most often, it is a JSP, in which case
Jasper, or the equivalent (not Struts), renders the page.
Struts….. fine–tuned further
The devil, as they say, is in the details. The synopsis and diagram in the prior sections do a good job of outlining the big picture but omit important details. Let’s drill down now and visit the finer points. Since this is HTTP, everything starts with an incoming request.
Request is received by our container
The backbone component of the Struts framework is the ActionServlet. Like all servlets, it lives in a container, such as Tomcat, Resin, or WebLogic. When the container boots, it reads a deployment descriptor (web.xml) that tells it which servlets to load. One of the standard servlet settings is the servlet mapping. The container uses this setting to decide which requests are sent to which servlet:
1 2 3 4
<servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>/do/*</url-pattern> </servlet-mapping>
Here, we have asked the container to give our ActionServlet any request that matches the pattern /do/*. That would include /do/This or /do/That and /do/ something/Whatever.Many applications like to use suffix mapping instead:
1 2 3 4
<servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.*.do/url-pattern> </servlet-mapping>
This URL pattern would likewise match this.do or that.do or /something/whatever.do. Any valid extension or prefix can be used; .do is simply a popular choice. When a request comes in with a path component that matches our servlet context, the container forwards it to our ActionServlet. Requests that do not match our pattern are not sent to the
ActionServlet. A request matching *.jsp, for example, would be forwarded to the container’s JSP service, such as Jasper if you are using Tomcat or WebSphere. There may be other servlets in your applications that handle other patterns. Any pattern that does not match a servlet mapping is sent to the container’s default web server.
Request is received by our ActionServlet
When our ActionServlet receives a request, it runs the request through a gauntlet that processes the locale, mapping, form bean, and finally the Action. Some of these steps apply only to Struts 1.1 applications:
Process MultipartRequest. If this is a multipart request (a form with a Multipurpose Internet Mail Extension [MIME] attachment), the servlet wraps the request with a special handler, to avoid errors later in the process.
Process Path. The ActionServlet checks to see if this path is for an application module. If so the configuration for the appropriate module is selected. [Struts 1.1] Process Locale. By default, the ActionServlet will check to see if there is a standard locale object in the user’s session. If there is no locale object, the ActionServlet will put
one there. This object can be used to provide a localized presentation for each user. Process Content and NoCache. The default MIME type and optional request headers are added to the response.
Process Mapping. The ActionServlet checks the ActionMappings for a mapping keyed to a path that matches the one we are processing. If one is not found, the ActionServlet forwards to the default (or “unknown”) Action, if one has been set, or generates a “bad request” error. If the mapping is found, it is placed into the request for future reference.
Process Roles. The ActionServlet checks to see if the user is authorized to access this action. [Struts 1.1]
Process ActionForm. The ActionServlet checks whether the mapping specifies an ActionForm. If it does, the servlet checks to see if one already exists in the specified scope. (The default is session.) If one does not exist, the ActionServlet creates one.
Process Populate. The ActionForm’s reset method is called, and then it is auto populated via reflection. Parameters that match the ActionForm’s properties are applied. Other parameters and properties are ignored.
Process Validate. The ActionForm’s validate method is called. If the method returns false, control is passed to the input property specified on the mapping, and the Action is not processed.
Process Forward or Include. If the ActionMapping specifies the forward or include attribute, control is transferred to another resource. Otherwise, the ActionServlet delegates the request to an Action object.
Process Action. If the mapping specifies an Action type, the servlet checks to see if one has already been instantiated. If it does not find one, the Action object is instantiated. There is only one Action object per class (the Singleton pattern), which handles all the requests for that Action through multithreading. The servlet calls the Action’s perform or execute method, passing the request, response, mapping, and any form bean. The Action
executes whatever behavior is required, which may include:
Accessing a data system, such as a JDBC database
- Creating objects in the request to be used by the view
- Creating objects in the user session, if required
- Updating session objects, such as the user’s locale, as needed
- Performing any other business function required by the application
- Handling exceptions and other error conditions
- Sending a direct response or (most often) returning an ActionForward to
A business object that is invoked by the Action (the Business Delegate pattern) often handles some of this behavior, like accessing a database. The Action is there to handle any web-specific tasks, but any code that can be placed in a business object should be placed in a business object. The Action is a Controller class and should not be used to
handle your application’s core business logic.