Struts 2 Architecture and Internal Components
Apache Struts 2 is an elegant, extensible framework for creating enterprise-ready Java web applications.
It is a second-generation web application framework that implements the Model-View-Controller (MVC) design pattern and it introduces several new architectural features that make the framework cleaner and more flexible. These new features includes-
- Interceptors for layering cross-cutting concerns away from action logic.
- Annotation-based configuration to reduce or eliminate XML configuration.
- A powerful expression language, Object-Graph Navigation Language(OGNL), that transverses the entire framework.
- A mini-MVC–based tag API that supports modifiable and reusable UI components.
- Pluggable architecture which supports framework extension.
- Better support for Validation, File Upload, Internationalization (I18N) through Interceptors.
Apache Struts2 was originally known as WebWork 2. After working independently for several years, the WebWork and Struts communities joined forces to create Struts2. This new version of Struts is simpler to use and closer to how Struts was always meant to be.
Struts 2 Architecture
Mainly the MVC pattern provides a separation of concerns that applies well to web applications. Separation of concerns means managing the complexity of large software systems by dividing them into high-level components. The MVC design pattern identifies three distinct concerns: model, view, and controller. In Struts 2, these are implemented by the action, result, and FilterDispatcher respectively.
The Big Picture of Struts2-
Struts 2 Framework Components
Now let us see some of the Back components (API Classes) of Struts2 framework-
This is the controller of Struts 2 framework and the first component to act in the request processing cycle. Basically it is a servlet filter. Its main and important job is to inspecting each incoming request to determine which Struts 2 action should handle the request.
This class is used by FilterDispatcher to determine whether the request should invoke an action or not.
When given an HttpServletRequest, the ActionMapper may return null if no action invocation request matches, or it may return an ActionMapping that describes an action invocation for the framework to try.
ActionMapping is the class that holds the action mapping information used to invoke a Struts action.
If the ActionMapper determines that an Action should be invoked for that request, the FilterDispatcher delegates control to the ActionProxy. The ActionProxy consults with ConfigurationManager and then creates an ActionInvocation.
This is the java object representation for the struts.xml file which is loaded at the application startup and contains all the information regarding framework configuration. The ConfigurationProvider interface describes the framework’s configuration. By default, the framework loads its configurations via an xml document by using the StrutsXmlConfigurationProvider.
This the core configuration files of struts 2 framework. It contains user defined mappings for each actions, Interceptors and results etc.
It is responsible for the command pattern implementation. This includes invoking any Interceptors in advance of invoking the Action itself. Once the Action returns, the ActionInvocation is responsible for looking up the proper result associated with the Action result code mapped in struts.xml. The result is then executed, which involves a template written in JSP or FreeMarker to be rendered.
Interceptors are invoked both before and after the action has executed. Interceptors don’t necessarily have to do something both times they fire, but they do have the opportunity. Some interceptors only do work
before the action has been executed, and others only do work afterward. The important thing is that the interceptor allows common, cross-cutting tasks to be defined in clean, reusable components that you can keep separate from your action code (e.g. validation, file upload, logging etc). You can use a stack of interceptors for a single action as well.
MVC model concern is implemented by the Struts 2 action component. In an application for a specific task, there should be a respective action to handle that particular task. Let’s take a user login scenario where there must be an action which is responsible for validating the user credentials with Database values. In a single line- An action is an encapsulation of the calls to business logic into a single unit of work.
Result translates the state of the application into a visual presentation with which the user can interact. The action is responsible for choosing which result will render the response for a specific request. Different Results types are like Jsp, Velocity, Freemaker etc.
It is the view pages which actually renders the response to the user.
Although ObjectFactory is not shown in above diagram, still this is one of the core important class of the framework. All objects created by the framework are instantiated by the ObjectFactory. The ObjectFactory provides the means of integrating the framework with IoC containers like Spring.
Request Processing Lifecycle
- The normal lifecycle of struts2 begins when the request is sent from client’s browser. This results invoke the servlet container which in turn is passed through standard filter chain. The chain includes the (optional) ActionContextCleanUp filter, which is useful when integrating technologies such as SiteMesh Plugin.
- The FilterDispatcher filter is called which consults the ActionMapper to determine whether an Action should be invoked.
- If ActionMapper finds an Action needs to be invoked, the FilterDispatcher delegates control to ActionProxy.
- ActionProxy reads the configuration file such as struts.xml. ActionProxy creates an instance of ActionInvocation class and delegates the control.
- ActionInvocation is responsible for command pattern implementation. It invokes the Interceptors one by one (if required) and then invoke the Action.
- Once the Action returns, the ActionInvocation is responsible for looking up the proper result associated with the Action result code mapped in struts.xml.
- The Interceptors are executed again in reverse order and the response is returned to the FilterDispatcher. And the result is then sent to the servlet container which in turns sends it back to client.
Comparison between Struts 1 and Struts 2
Let us see the basic difference between Struts 1 and 2 frameworks-
- Unlike Struts 1, Struts 2 does not need to extend Action class. The Action in Struts 2 is a POJO object. Thus making it easy to unit test the code.
- Struts 1 Actions are singletons and must be thread-safe since there will be only one instance of a class to handle all requests for that Action. Struts 2 Action objects are instantiated for each request, so there are no thread-safety issues.
- Struts 1 Actions have dependencies on the servlet API since the HttpServletRequest and HttpServletResponse is passed to the execute method when an Action is invoked. Struts 2 Actions are not coupled to a container. Most often the servlet contexts are represented as simple Maps, allowing Actions to be tested in isolation.
- Struts 1 uses an ActionForm object to capture input. Like Actions, all ActionForms must extend a base class. Since other JavaBeans cannot be used as ActionForms, developers often create redundant classes to capture input. Struts 2 uses Action properties as input properties, eliminating the need for a second input object. Input properties may be rich object types which may have their own properties.
- Struts 1 integrates with JSTL, so it uses the JSTL EL. The EL has basic object graph traversal, but relatively weak collection and indexed property support. Struts 2 can use JSTL, but the framework also supports a more powerful and flexible expression language called “Object Graph Notation Language” (OGNL).
- Struts 1 uses the standard JSP mechanism for binding objects into the page context for access. Struts 2 uses a “ValueStack” technology so that the taglibs can access values without coupling your view to the object type it is rendering.
- Struts 1 supports separate Request Processors (lifecycles) for each module, but all the Actions in the module must share the same lifecycle. Struts 2 supports creating different lifecycles on a per Action basis via Interceptor Stacks. Custom stacks can be created and used with different Actions, as needed.
You can find the Strut2-jQuery plugin showcase at HereFollow Me On: