Monday, 18 June 2012

Interceptor achieve Modularity

The default Interceptor stack is designed to serve the needs of most applications. Most applications will not need to add Interceptors or change the Interceptor stack.

Many Actions share common concerns. Some Actions need input
validated. Other Actions may need a file upload to be pre-processed.
Another Action might need protection from a double submit. Many Actions
need drop-down lists and other controls pre-populated before the page
displays.
The framework makes it easy to share solutions to these concerns
using an "Interceptor" strategy. When you request a resource that maps
to an "action", the framework invokes the Action object. But, before the
Action is executed, the invocation can be intercepted by another
object. After the Action executes, the invocation could be intercepted
again. Unsurprisingly, we call these objects "Interceptors."

Understanding Interceptors

Interceptors can execute code before and after an Action is invoked.
Most of the framework's core functionality is implemented as
Interceptors. Features like double-submit guards, type conversion,
object population, validation, file upload, page preparation, and more,
are all implemented with the help of Interceptors. Each and every
Interceptor is pluggable, so you can decide exactly which features an
Action needs to support.
Interceptors can be configured on a per-action basis. Your own custom
Interceptors can be mixed-and-matched with the Interceptors bundled
with the framework. Interceptors "set the stage" for the Action classes,
doing much of the "heavy lifting" before the Action executes.

Action Lifecyle

In some cases, an Interceptor might keep an Action from firing,
because of a double-submit or because validation failed. Interceptors
can also change the state of an Action before it executes.
The Interceptors are defined in a stack that specifies the execution
order. In some cases, the order of the Interceptors on the stack can be
very important.

Stacking Interceptors

With most web applications, we find ourselves wanting to apply the
same set of Interceptors over and over again. Rather than reiterate the
same list of Interceptors, we can bundle these Interceptors together
using an Interceptor Stack.

Since the struts-default.xml is included in the
application's configuration by default, all of the predefined
interceptors and stacks are available "out of the box".

Framework Interceptors

Interceptor classes are also defined using a key-value pair specified
in the Struts configuration file. The names specified below come
specified in struts-default.xml. If you extend the struts-default
package, then you can use the names below. Otherwise, they must be
defined in your package with a name-class pair specified in the
<interceptors> tag.

Adds automatic checkbox handling code that
detect an unchecked checkbox and add it as a parameter with a default
(usually 'false') value. Uses a specially named hidden field to detect
unsubmitted checkboxes. The default unchecked value is overridable for
non-boolean value'd checkboxes.

Since
2.0.7, Interceptors and Results with hyphenated names were converted to
camelCase. (The former model-driven is now modelDriven.) The original
hyphenated names are retained as "aliases" until Struts 2.1.0. For
clarity, the hyphenated versions are not listed here, but might be
referenced in prior versions of the documentation.

Method Filtering

An abstract Interceptor that is applied to filter method names according
to specified included/excluded method lists.
Setable parameters are as follows:

excludeMethods - methods name to be excluded

includeMethods - methods name to be included

NOTE: If method name are available in both includeMethods and
excludeMethods, it will still be considered as an included method. In short
includeMethods takes precedence over excludeMethods.
Interceptors that extends this capability would be :-

TokenInterceptor

TokenSessionStoreInterceptor

DefaultWorkflowInterceptor

ValidationInterceptor

Interceptor Parameter Overriding

Interceptor's parameter could be overriden through the following ways :-Method 1:

In the first method, the whole default stack is copied and the parameter then
changed accordingly.
In the second method, the refer to an existing
interceptor-stack, namely default-stack in this example, and override the validator
and workflow interceptor excludeMethods typically in this case. Note that in the
tag, the name attribute contains a dot (.) the word before the dot(.)
specifies the interceptor name whose parameter is to be overriden and the word after
the dot (.) specifies the parameter itself. Essetially it is as follows :-

<interceptor-name>.<parameter-name>

Note also that in this case the name attribute
is used to indicate an interceptor stack which makes sense as if it is refering
to the interceptor itself it would be just using Method 1 describe above.

Note that some Interceptors will interrupt the stack/chain/flow ... so the order is very important.
Interceptors implementing com.opensymphony.xwork2.interceptor.PreResultListener will run after the Action executes but before the Result executes.

-->The default Interceptor stack is designed to serve the needs of most applications. Most applications will not need to add (register) Interceptors or change the Interceptor stack.Therefore we don't need to explicitly register default interceptors eith <interceptor-ref> before using them.

->Since there are lot of things to do in FilterDispatcher.However code reside in FilterDispatcher would be modularize into diffrent interceptors plugged in and out in struts.xml file.Hence new code for action processing can be added without recompiling the framework

-->Custom Interceptor must be register before use.However there is no need to register default interceptor

->Unlike actions, interceptors are reused across requests and need to be thread-safe, especially the intercept() method.

-->It should be noted that you can register more than one interceptors inside <package> tag and same time you can call more than one interceptors inside the <action> tag. You can call same interceptor with the different actions.

Interceptors are conceptually the same as servlet filters or the JDKs
Proxy class. Interceptors allow for crosscutting functionality to be
implemented separately from the action as well as the framework. You can
achieve the following using interceptors:

Providing preprocessing logic before the action is called.

Providing postprocessing logic after the action is called.

Catching exceptions so that alternate processing can be performed.

Many of the features provided in the Struts2 framework are
implemented using interceptors; examples include exception handling,
file uploading, lifecycle callbacks and validation etc. In fact, as
Struts2 bases much of its functionality on interceptors,
it is not unlikely to have 7 or 8 interceptors assigned per action.

Some common Interceptors:

Struts 2 framework provides a good list of out-of-the-box
interceptors that come preconfigured and ready to use. Few of the
important interceptors are listed below:

SN

Interceptor & Description

1

alias
Allows parameters to have different name aliases across requests.

2

checkbox
Assists in managing check boxes by adding a parameter value of false for check boxes that are not checked.

3

conversionError
Places error information from converting strings to parameter types into the action's field errors.

4

createSession
Automatically creates an HTTP session if one does not already exist.

5

debugging
Provides several different debugging screens to the developer.

6

execAndWait
Sends the user to an intermediary waiting page while the action executes in the background.

7

exception
Maps exceptions that are thrown from an action to a result, allowing automatic exception handling via redirection.

8

fileUpload
Facilitates easy file uploading.

9

i18n
Keeps track of the selected locale during a user's session.

10

logger
Provides simple logging by outputting the name of the action being executed.

11

params
Sets the request parameters on the action.

12

prepare
This is typically used to do pre-processing work, such as setup database connections.

13

profile
Allows simple profiling information to be logged for actions.

14

scope
Stores and retrieves the action's state in the session or application scope.

15

ServletConfig
Provides the action with access to various servlet-based information.

16

timer
Provides simple profiling information in the form of how long the action takes to execute.

17

token
Checks the action for a valid token to prevent duplicate formsubmission.

18

validation
Provides validation support for actions

Please loook into Struts 2 documentation for complete detail on above
mentioned interceptors. But I will show you how to use an interceptor
in general in your Struts application.

How to use Interceptors?

Let us see how to use an already existing interceptor to our "Hello World" program. We will use the timer interceptor whose purpose is to measure how long it took to execute an action method. Same time I'm using params
interceptor whose purpose is to send the request parameters to the
action. You can try your example without using this interceptor and you
will find that name property is not being set because parameter is not able to reach to the action.
We will keep HelloWorldAction.java, web.xml, HelloWorld.jsp and
index.jsp files as they have been created in Examples chapter but let us
modify the struts.xml file to add an interceptor as follows

Right click on the project name and click Export > WAR File
to create a War file. Then deploy this WAR in the Tomcat's webapps
directory. Finally, start Tomcat server and try to access URL
http://localhost:8080/HelloWorldStruts2/index.jsp. This will give you
following screen:

Now enter any word in the given text box and click Say Hello button
to execute the defined action. Now if you will check the log generated,
you will find following text:

Here bottom line is being generated because of timer interceptor which is telling that action took total 109ms to be executed.

Create Custom Interceptors

Using custom interceptors in your application is an elegant way to
provide cross-cutting application features. Creating a custom
interceptor is easy; the interface that needs to be extended is the
following Interceptor interface:

As the names suggest, the init() method provides a way to initialize
the interceptor, and the destroy() method provides a facility for
interceptor cleanup. Unlike actions, interceptors are reused across
requests and need to be thread-safe, especially the intercept() method.
The ActionInvocation object provides access to the runtime
environment. It allows access to the action itself and methods to invoke
the action and determine whether the action has already been invoked.
If you have no need for initialization or cleanup code, the AbstractInterceptor class can be extended. This provides a default no-operation implementation of the init() and destroy() methods.

As you notice, actual action will be executed using the interceptor by invocation.invoke() call. So you can do some pre-processing and some post-processing based on your requirement.
The framework itself starts the process by making the first call to the ActionInvocation object's invoke(). Each time invoke()
is called, ActionInvocation consults its state and executes whichever
interceptor comes next. When all of the configured interceptors have
been invoked, the invoke() method will cause the action itself to be
executed. Following digram shows the same concept through a request
flow:

Create Action Class:

Let us create a java file HelloWorldAction.java under Java Resources > src with a package name com.tutorialspoint.struts2 with the contents given below.

Create main page:

We also need to create index.jsp in the WebContent folder.
This file will serve as the initial action URL where a user can click to
tell the Struts 2 framework to call the a defined method of the
HelloWorldAction class and render the HelloWorld.jsp view.

The hello action defined in the above view file will be mapped
to the HelloWorldAction class and its execute method using struts.xml
file.

Configuration Files

Now we need to register our interceptor and then call it as we had
called default interceptor in previous example. To register a newly
defined interceptor, the <interceptors>...</interceptors>
tags are placed directly under the <package> tag ins struts.xml
file. You can skip this step for a default interceptors as we did in
our previous example. But here let us register and use it as follows:

It should be noted that you can register more than one interceptors inside <package> tag and same time you can call more than one interceptors inside the <action> tag. You can call same interceptor with the different actions.
The web.xml file needs to be created under the WEB-INF folder under WebContent as follows:

Right click on the project name and click Export > WAR File
to create a War file. Then deploy this WAR in the Tomcat's webapps
directory. Finally, start Tomcat server and try to access URL
http://localhost:8080/HelloWorldStruts2/index.jsp. This will give you
following screen:

Now enter any word in the given text box and click Say Hello button
to execute the defined action. Now if you will check the log generated,
you will find following text at the bottom:

Pre-Processing
Inside action....
Post-Processing

Stacking multiple Interceptors:

As you can imagine, having to configure multiple interceptor for each
action would quickly become extremely unmanageable. For this reason,
interceptors are managed with interceptor stacks. Here is an example,
directly from the struts-default.xml file:

The above stake is called basicStack and can be used in your
configuration as shown below. This configuration node is placed under
the <package .../> node. Each <interceptor-ref .../> tag
references either an interceptor or an interceptor stack that has been
configured before the current interceptor stack. It is therefore very
important to ensure that the name is unique across all interceptor and
interceptor stack configurations when configuring the initial
interceptors and interceptor stacks.
We have already seen how to apply interceptor to the action, applying
interceptor stacks is no different. In fact, we use exactly the same
tag:

The above registration of "basicStack" will register complete stake
of all the six interceptors with hello action. This should be noted that
interceptors are executed in the order, in which they have been
configured. For example, in above case, exception will be executed
first, second would be servlet-config and so on.