This article introduces Struts as a framework for rapid Model 2 application development. It starts with a discussion of the benefits of Struts and how it expedites Model 2 application development. It also discusses the basic components of Struts: the filter dispatcher, actions, results, and interceptors.
Introducing Struts configuration is another objective of this article. Most Struts application will have a struts.xml file and a struts.properties file. The former is the more important as it is where you configure your actions. The latter is optional as there exists a default.properties file that contains standard settings that work for most applications.
The Benefits of Struts
Struts is an MVC framework that employs a filter dispatcher as the controller. When writing a Model 2 application, it is your responsibility to provide a controller as well as write action classes. Your controller must be able to do these:
1. Determine from the URI what action to invoke.
2. Instantiate the action class.
3. If an action object exists, populate the action’s properties with request parameters.
4. If an action object exists, call the action method.
5. Forward the request to a view (JSP).
The first benefit of using Struts is that you don’t have to write a controller and can concentrate on writing business logic in action classes. Here is the list of features that Struts is equipped with to make development more rapid:
• Struts provides a filter dispatcher, saving you writing one.
• Struts employs an XML-based configuration file to match URIs with actions. Since XML documents are text files, many changes can be made to the application without recompilation.
• Struts instantiates the action class and populates action properties with user inputs. If you don’t specify an action class, a default action class will be instantiated.
• Struts validates user input and redirects user back to the input form if validation failed. Input validation is optional and can be done programmatically or declaratively. On top of that, Struts provides built-in validators for most of the tasks you may encounter when building a web application.
• Struts invokes the action method and you can change the method for an action through the configuration file.
• Struts examines the action result and executes the result. The most common result type, Dispatcher, forwards control to a JSP. However, Struts comes with various result types that allow you to do things differently, such as generate a PDF, redirect to an external resource, send an error message, etc.
The list shows how Struts can help you with the tasks you did when developing Model 2 applications .There is much more. Custom tags for displaying data, data conversion, support for AJAX, support for internationalization and localization, and extension through plug-ins are some of them.
How Struts Works
Struts has a filter dispatcher similar to that in app01b. Its fully qualified name is org.apache.struts2.dispatcher.FilterDispatcher. To use it, register it in the deployment descriptor (web.xml file) using this filter and filter-mapping elements.
There’s a lot that a filter dispatcher in a Model 2 application has to do and Struts’ filter dispatcher is by no means an exception. Since Struts has more, actually much more, features to support, its filter dispatcher could grow infinitely in complexity. However, Struts approaches this by splitting task processing in its filter dispatcher into subcomponents called interceptors. The first interceptor you’ll notice is the one that populates the action object with request parameters. In a Struts application the action method is executed after the action’s properties are populated. An action method can have any name as long as it is a valid Java method name.
An action method returns a String value. This value indicates to Struts where control should be forwarded to. A successful action method execution will forward to a different view than a failed one. For instance, the String “success” indicates a successful action method execution and “error” indicates that there’s been an error during processing and an error message should be displayed. Most of the time a RequestDispatcher will be used to forward to a JSP, however JSPs are not the only allowed destination. A result that returns a file for download does not need a JSP. Neither does a result that simply sends a redirection command or sends a chart to be rendered. Even if an action needs to be forwarded to a view, the view may not necessarily be a JSP. A Velocity template or a FreeMarker template can also be used.
Now that you know all the basic components in Struts, I’ll continue by explaining how Struts works. Since Struts uses a filter dispatcher as its controller, all activities start from this object
The first things that a filter dispatcher does is verify the request URI and determine what action to invoke and which Java action class to instantiate. The filter dispatcher in app01b did this by using a string manipulation method. However, this is impractical since during development the URI may change several times and you will have to recompile the filter each time the URI or something else changes.
For matching URIs with action classes, Struts uses a configuration file named struts.xml. Basically, you need to create a struts.xml file and place it under WEB-INF/classes. You define all actions in the application in this file. Each action has a name that directly corresponds to the URI used to invoke the action. Each action declaration may specify the fully qualified name of an action class, if any. You may also specify the action method name unless its name is execute, the default method name Struts will assume in the absence of an explicit one.
An action class must have at least one result to tell Struts what to do after it executes the action method. There may be multiple results if the action method may return different results depending on, say, user inputs.
The struts.xml file is read when Struts starts. In development mode, Struts checks the timestamp of this file every time it processes a request and will reload it if it has changed since the last time it was loaded. As a result, if you are in development mode and you change the struts.xml file, you don’t need to restart your web container. Saving you time.
Configuration file loading will fail if you don’t comply with the rules that govern the struts.xml file. If, or should I say when, this happens, Struts will fail to start and you must restart your container. Sometimes it’s hard to decipher what you’ve done wrong due to unclear error messages. If this happens, try commenting out actions that you suspect are causing it, until you isolate and fix the one that is impending development.
For every action invocation the filter dispatcher does the following:
1. Consult the Configuration Manager to determine what action to invoke based on the request URI:
2. Run each of the interceptors registered for this action. One of the interceptors will populate the action’s properties.
3. Execute the action method.
4. Execute the result.
Note that some interceptors run again after action method execution, before the result is executed.
As mentioned earlier, there are a lot of things a filter dispatcher must do. Code that would otherwise reside in the filter dispatcher class is modularized into interceptors. The beauty of interceptors is they can be plugged in and out by editing the Struts’ configuration file. Struts achieves a high degree of modularity using this strategy. New code for action processing can be added without recompiling the main framework.
The table below lists Struts default interceptors. The words in brackets in the Interceptor column are names used to register the interceptors in the configuration file. Yes, as you will see shortly, you need to register an interceptor in the configuration file before you can use it. For example, the registered name for the Alias interceptor is alias.
Struts default interceptors
Alias (alias) Converts similar parameters that may have different names between requests.
Chaining (chain) When used with the Chain result type, this interceptor makes the previous action’s properties available to the current action.
Checkbox (checkbox) Handles check boxes in a form so that unchecked check boxes can be detected
Cookie (cookie) Adds a cookie to the current action.
Conversion Error (conversionError) Adds conversion errors to the action’s field errors.
Create Session (createSession) Creates an HttpSession object if one does not yet exist for the current user.
Debugging (debugging) Supports debugging.
Execute and Wait (execAndWait) Executes a long-processing action in the background and sends the user to an intermediate waiting page.
Exception (exception) Maps exceptions to a result.
File Upload (fileUpload) Supports file upload.
I18n (i18n) Supports internationalization and localization
Logger (logger) Outputs the action name.
Message Store (store) Stores and retrieves action messages or action errors or field errors for action objects whose classes implement ValidationAware.
Model Driven (modelDriven) Supports for the model driven pattern for action classes that implement ModelDriven.
Scoped Model Driven (scopedModelDriven) Similar to the Model Driven interceptor but works for classes that implementScopedModelDriven.
Parameters (params) Populates the action’s properties with the request parameters.
Prepare (prepare) Supports action classes that implement thePreparable interface.
Scope (scope) Provides a mechanism for storing action state in the session or application scope.
Servlet Config (servletConfig) Provides access to the Maps representingHttpServletRequest andHttpServletResponse.
Static Parameters (staticParams) Maps static properties to action properties.
Roles (roles) Supports role-based action.
Timer (timer) Outputs the time needed to execute an action.
Token (token) Verifies that a valid token is present
Token Session (tokenSession) Verifies that a valid token is present
Validation (validation) Supports input validation.
Workflow (workflow) Calls the validate method in the action class.
Parameter Filter (n/a) Removes parameters from the list of those available to the action.
Profiling (profiling) Supports action profiling.
There are quite a number of interceptors, and this can be confusing to a beginner. The thing is you don’t have to know about interceptors intimately before you can write a Struts application.
Just know that interceptors play a vital role in Struts and we will revisit them one at a time in subsequent articles.
Most of the time the default interceptors are good enough. However, if you need non-standard action processing, you can write your own interceptor.
Struts Configuration Files
A Struts application uses a number of configuration files. The primary two are struts.xml and struts.properties, but there can be other configuration files. For instance, a Struts plug-in comes with a struts-plugin.xml configuration file. And if you’re using Velocity as your view technology, expect to have a velocity.properties file.
In struts.xml you define all aspects of your application, including the actions, the interceptors that need to be called for each action, and the possible results for each action.
Interceptors and result types used in an action must be registered before they can be used. Happily, Struts configuration files support inheritance and default configuration files are included in the struts2-core- VERSION.jar file. The struts-default.xml file, one of such default configuration files, registers the default result types and interceptors. As such, you can use the default result types and interceptors without registering them in your own struts.xml file, making it cleaner and shorter.
The default.properties file, packaged in the same JAR, contains settings that apply to all Struts applications. As a result, unless you need to override the default values, you don’t need to have a struts.properties file.
For Configuration details there will be a detailed article about struts.xml and struts.properties in more detail.
Struts 2 Design and Programming: A Tutorial
By: Budi Kurniawan