interceptors in struts2

48
Interceptors Edit Page Browse Space Add Page Add News Added by victorsosa , last edited by Ted Husted on Mar 17, 2007 (view change ) 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.

Upload: yugandharch

Post on 19-Nov-2014

134 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Interceptors in Struts2

InterceptorsEdit Page   Browse Space   Add Page   Add News

Added by victorsosa, last edited by Ted Husted on Mar 17, 2007  (view change)

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

Page 2: Interceptors in Struts2

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.

Configuring Interceptors

struts.xml<package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> </interceptors>

<action name="login" class="tutorial.Login"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <result name="input">login.jsp</result> <result name="success" type="redirect-action">/secure/home</result> </action></package>

Stacking Interceptors

Page 3: Interceptors in Struts2

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.

struts.xml<package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> <interceptor-stack name="myStack"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> </interceptor-stack> </interceptors>

<action name="login" class="tutuorial.Login"> <interceptor-ref name="myStack"/> <result name="input">login.jsp</result> <result name="success" type="redirect-action">/secure/home</result></action></package>

Looking inside struts-default.xml, we can see how it's done.

The Default Configuration

<?xml version="1.0" encoding="UTF-8" ?><!--/* * $Id$ * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */-->

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

Page 4: Interceptors in Struts2

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts> <bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" /> <bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />

<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="xwork" class="com.opensymphony.xwork2.DefaultActionProxyFactory"/> <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.impl.StrutsActionProxyFactory"/>

<bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="tiger" class="com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer"/> <bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="notiger" class="com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"/> <bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="struts" class="com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"/>

<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" class="org.apache.struts2.dispatcher.mapper.DefaultActionMapper" /> <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="composite" class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" /> <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful" class="org.apache.struts2.dispatcher.mapper.RestfulActionMapper" /> <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful2" class="org.apache.struts2.dispatcher.mapper.Restful2ActionMapper" />

<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="struts" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true"/> <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true" />

<bean type="org.apache.struts2.views.TagLibrary" name="s" class="org.apache.struts2.views.DefaultTagLibrary" />

<bean class="org.apache.struts2.views.freemarker.FreemarkerManager" name="struts" optional="true"/> <bean class="org.apache.struts2.views.velocity.VelocityManager" name="struts" optional="true" />

<bean class="org.apache.struts2.components.template.TemplateEngineManager" />

Page 5: Interceptors in Struts2

<bean type="org.apache.struts2.components.template.TemplateEngine" name="ftl" class="org.apache.struts2.components.template.FreemarkerTemplateEngine" /> <bean type="org.apache.struts2.components.template.TemplateEngine" name="vm" class="org.apache.struts2.components.template.VelocityTemplateEngine" /> <bean type="org.apache.struts2.components.template.TemplateEngine" name="jsp" class="org.apache.struts2.components.template.JspTemplateEngine" />

<bean type="com.opensymphony.xwork2.util.XWorkConverter" name="xwork1" class="com.opensymphony.xwork2.util.XWorkConverter" /> <bean type="com.opensymphony.xwork2.util.XWorkConverter" name="struts" class="com.opensymphony.xwork2.util.AnnotationXWorkConverter" />

<bean type="com.opensymphony.xwork2.TextProvider" name="xwork1" class="com.opensymphony.xwork2.TextProviderSupport" /> <bean type="com.opensymphony.xwork2.TextProvider" name="struts" class="com.opensymphony.xwork2.TextProviderSupport" />

<bean type="org.apache.struts2.components.UrlRenderer" name="struts" class="org.apache.struts2.components.ServletUrlRenderer"/>

<!-- Only have static injections --> <bean class="com.opensymphony.xwork2.ObjectFactory" static="true" /> <bean class="com.opensymphony.xwork2.util.XWorkConverter" static="true" /> <bean class="com.opensymphony.xwork2.util.OgnlValueStack" static="true" /> <bean class="org.apache.struts2.dispatcher.Dispatcher" static="true" /> <bean class="org.apache.struts2.components.Include" static="true" /> <bean class="org.apache.struts2.dispatcher.FilterDispatcher" static="true" /> <bean class="org.apache.struts2.views.util.ContextUtil" static="true" /> <bean class="org.apache.struts2.views.util.UrlHelper" static="true" />

<package name="struts-default" abstract="true"> <result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>

Page 6: Interceptors in Struts2

<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> </result-types>

<interceptors> <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" /> <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> <interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/> <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/> <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/> <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/> <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/> <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>

Page 7: Interceptors in Struts2

<interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/> <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/> <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/> <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/> <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/> <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" /> <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" /> <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" /> <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" /> <interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" /> <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />

<!-- Basic stack --> <interceptor-stack name="basicStack"> <interceptor-ref name="exception"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> </interceptor-stack>

<!-- Sample validation and workflow stack --> <interceptor-stack name="validationWorkflowStack"> <interceptor-ref name="basicStack"/> <interceptor-ref name="validation"/> <interceptor-ref name="workflow"/> </interceptor-stack> <!-- Sample JSON validation stack --> <interceptor-stack name="jsonValidationWorkflowStack"> <interceptor-ref name="basicStack"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> <interceptor-ref name="jsonValidation"/> <interceptor-ref name="workflow"/> </interceptor-stack>

Page 8: Interceptors in Struts2

<!-- Sample file upload stack --> <interceptor-stack name="fileUploadStack"> <interceptor-ref name="fileUpload"/> <interceptor-ref name="basicStack"/> </interceptor-stack>

<!-- Sample model-driven stack --> <interceptor-stack name="modelDrivenStack"> <interceptor-ref name="modelDriven"/> <interceptor-ref name="basicStack"/> </interceptor-stack>

<!-- Sample action chaining stack --> <interceptor-stack name="chainStack"> <interceptor-ref name="chain"/> <interceptor-ref name="basicStack"/> </interceptor-stack>

<!-- Sample i18n stack --> <interceptor-stack name="i18nStack"> <interceptor-ref name="i18n"/> <interceptor-ref name="basicStack"/> </interceptor-stack>

<!-- An example of the params-prepare-params trick. This stack is exactly the same as the defaultStack, except that it includes one extra interceptor before the prepare interceptor: the params interceptor.

This is useful for when you wish to apply parameters directly to an object that you wish to load externally (such as a DAO or database or service layer), but can't load that object until at least the ID parameter has been loaded. By loading the parameters twice, you can retrieve the object in the prepare() method, allowing the second params interceptor to apply the values on the object. --> <interceptor-stack name="paramsPrepareParamsStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="params"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="params"/>

Page 9: Interceptors in Struts2

<interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> </interceptor-stack>

<!-- A complete stack with all the common interceptors in place. Generally, this stack should be the one you use, though it may do more than you need. Also, the ordering can be switched around (ex: if you wish to have your servlet-related objects applied before prepare() is called, you'd need to move servlet-config interceptor up.

This stack also excludes from the normal validation and workflow the method names input, back, and cancel. These typically are associated with requests that should not be validated. --> <interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="debugging"/> <interceptor-ref name="profiling"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack>

Page 10: Interceptors in Struts2

<!-- The completeStack is here for backwards compatibility for applications that still refer to the defaultStack by the old name --> <interceptor-stack name="completeStack"> <interceptor-ref name="defaultStack"/> </interceptor-stack>

<!-- Sample execute and wait stack. Note: execAndWait should always be the *last* interceptor. --> <interceptor-stack name="executeAndWaitStack"> <interceptor-ref name="execAndWait"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> <interceptor-ref name="defaultStack"/> <interceptor-ref name="execAndWait"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> </interceptor-stack>

</interceptors>

<default-interceptor-ref name="defaultStack"/> </package>

</struts>

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.

Interceptor Name Description

Alias Interceptor alias Converts similar parameters that may be named differently between requests.

Chaining Interceptor chain

Makes the previous Action's properties available to the current Action. Commonly used together with <result type="chain"> (in the previous Action).

Checkbox Interceptor checkbox Adds automatic checkbox handling code that detect an unchecked checkbox and add it as a

Page 11: Interceptors in Struts2

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.

Cookie Interceptor cookie Inject cookie with a certain configurable name / value into action. (Since 2.0.7.)

Conversion Error Interceptor

conversionError Adds conversion errors from the ActionContext to the Action's field errors

Create Session Interceptor

createSession Create an HttpSession automatically, useful with certain Interceptors that require a HttpSession to work properly (like the TokenInterceptor)

DebuggingInterceptor debugging Provides several different debugging screens to provide insight into the data behind the page.

Execute and Wait Interceptor

execAndWait Executes the Action in the background and then sends the user off to an intermediate waiting page.

Exception Interceptor exception Maps exceptions to a result.

File Upload Interceptor fileUpload An Interceptor that adds easy access to file upload support.

I18n Interceptor i18n Remembers the locale selected for a user's session.

Logger Interceptor logger Outputs the name of the Action.

Message Store Interceptor

store Store and retrieve action messages / errors / field errors for action that implements ValidationAware interface into session.

Model Driven Interceptor

model-driven If the Action implements ModelDriven, pushes the getModel Result onto the Value Stack.

Scoped Model Driven Interceptor

scoped-model-driven

If the Action implements ScopedModelDriven, the interceptor retrieves and stores the model from a scope and sets it on the action calling setModel.

Parameters Interceptor params Sets the request parameters onto the Action.

Prepare Interceptor prepare If the Action implements Preparable, calls its prepare method.

Scope Interceptor scope Simple mechanism for storing Action state in the session or application scope.

Servlet Config Interceptor

servletConfig Provide access to Maps representing HttpServletRequest and HttpServletResponse.

Static Parameters Interceptor

staticParams Sets the struts.xml defined parameters onto the action. These are the <param> tags that are direct children of the <action> tag.

Roles Interceptor roles Action will only be executed if the user has the correct JAAS role.

Page 12: Interceptors in Struts2

Timer Interceptor timer Outputs how long the Action takes to execute (including nested Interceptors and View)

Token Interceptor token Checks for valid token presence in Action, prevents duplicate form submission.

Token Session Interceptor

tokenSession Same as Token Interceptor, but stores the submitted data in session when handed an invalid token

Validation Interceptor validation Performs validation using the validators defined in action-validation.xml

Workflow Interceptor workflow Calls the validate method in your Action class. If Action errors are created then it returns the INPUT view.

Parameter Filter Interceptor

N/A Removes parameters from the list of those available to Actions

Profiling Interceptor profiling Activate profiling through parameter

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

Page 13: Interceptors in Struts2

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

Method 1:

<action name="myAction" class="myActionClass"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="params"/> <interceptor-ref name="servlet-config"/> <interceptor-ref name="prepare"/> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="model-driven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="static-params"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">myValidationExcudeMethod</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">myWorkflowExcludeMethod</param> </interceptor-ref></action>

Method 2:

<action name="myAction" class="myActionClass"> <interceptor-ref name="defaultStack"> <param name="validation.excludeMethods">myValidationExcludeMethod</param> <param name="workflow.excludeMethods">myWorkflowExcludeMethod</param> </interceptor-ref></action>

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.

Page 14: Interceptors in Struts2

Order of Interceptor Execution

Interceptors provide an excellent means to wrap before/after processing. The concept reduces code duplication (think AOP).

<interceptor-stack name="xaStack"> <interceptor-ref name="thisWillRunFirstInterceptor"/> <interceptor-ref name="thisWillRunNextInterceptor"/> <interceptor-ref name="followedByThisInterceptor"/> <interceptor-ref name="thisWillRunLastInterceptor"/></interceptor-stack>

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.

thisWillRunFirstInterceptor thisWillRunNextInterceptor followedByThisInterceptor thisWillRunLastInterceptor MyAction1 MyAction2 (chain) MyPreResultListener MyResult (result) thisWillRunLastInterceptor followedByThisInterceptor thisWillRunNextInterceptorthisWillRunFirstInterceptor

FAQ

How do we configure an Interceptor to be used with every Action ? How do we get access to the session ? How can we access the HttpServletRequest ? How can we access the HttpServletResponse ? How can we access request parameters passed into an Action ? How do we access static parameters from an Action ? Can we access an Action's Result ? How do I obtain security details (JAAS) ? Why isn't our Prepare interceptor being executed ? How do we upload files ?

Next: Writing Interceptors

How do we configure an Interceptor to be used with every Action

Page 15: Interceptors in Struts2

Edit Page   Browse Space   Add Page   Add NewsAdded by Ted Husted, last edited by Ted Husted on Nov 08, 2006

Any given action mapping can create an "ad-hoc" interceptor stack

<action name="login" class="tutorial.Login">

<interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <interceptor-ref name="default-stack"/>

<result name="input">login.jsp</result> <result type="redirect-action">/secure/home</result> </action>

Or, we can create our own named stacks and even declare a new default interceptor stack for a package

<package name="default" extends="struts-default" > <interceptors> <interceptor-stack name="myStack"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <interceptor-ref name="default-stack"/> </interceptor-stack> </interceptors>

<default-interceptor-ref name="myStack"/>

<action name="login" class="tutorial.Login"> <result name="input">login.jsp</result> <result type="redirect-action">/secure/home</result> </action>

</package>

Packages can extend other packages. If all the other packages in your application extend "default", then they will all inherit the new default interceptor.

How do we get access to the sessionEdit Page   Browse Space   Add Page   Add News

Added by digi9ten, last edited by Ted Husted on Jul 22, 2006  (view change)

You can obtain the session attributes by asking the ActionContext or implementing SessionAware. Implementing SessionAware is preferred.

Ask the ActionContext

The session attributes are available on the ActionContext instance, which is made available via ThreadLocal.

Page 16: Interceptors in Struts2

Map attibutes = ActionContext.getContext().getSession();

Implement SessionAware

_Preferred_

Ensure that servlet-config Interceptor is included in the Action's stack. o The default stack already includes servlet-config.

Edit the Action so that it implements the SessionAware interface. o The SessionAware interface expects a setSession method. You may

wish to include a companion getSession method. At runtime, call getSession to obtain a Map representing the session attributes. Any changes made to the session Map are reflected in the actual

HttpSessionRequest. You may insert and remove session attributes as needed.

Map parameters = this.getSession();

When the servlet-config Interceptor sees that an Action implements ParameterAware, it passes a Map of the session attributes to the Action's setParameters method. Changes made to the Map are reflected in the runtime HttpSessionRequest.

To unit test a SessionAware Action, create your own Map with the pertinent session attributes and call setSession as part of the test's setUp method.

How can we access the HttpServletRequestEdit Page   Browse Space   Add Page   Add News

Added by digi9ten, last edited by Ted Husted on Jul 22, 2006  (view change)

You can obtain the request by asking the ActionContext or implementing ServletRequestAware. Implementing ServletRequestAwareis preferred.

Ask the ActionContext

The request is available on the ActionContext instance, which is made available via ThreadLocal.

HttpServletRequest request = ServletActionContext.getRequest();

Implement ServletRequestAware

Preferred

Ensure that servlet-config Interceptor is included in the Action's stack. o The default stack already includes servlet-config.

Page 17: Interceptors in Struts2

Edit the Action so that it implements the ServletRequestAware interface. o The ServletRequestAware interface expects a setServletRequest

method. You may wish to include a companion getServletRequest method.

At runtime, call getServletRequest to obtain a reference to the request object.

When the servlet-config Interceptor sees that an Action implements ServletRequestAware, it passes a reference to the request the Action's setServletRequest method.

It is more difficult to test Actions with runtime dependencies on HttpServletRequest. Only implement ServletRequestAware as a last resort. If the use case cannot be solved by one of the other servet-config interfaces (ApplicationAware, SessionAware, ParameterAware), consider whether an custom Interceptor could be used instead of Action code. (Review how servlet-config works for examples of what can be done.)

How can we access the HttpServletResponse Edit Page   Browse Space   Add Page Add News Added by tm_jee, last edited by Ted Husted on Jul 22, 2006  (view change)

You can obtain the request by asking the ActionContext or implementing ServletResponseAware. Implementing ServletResponseAware is preferred.Ask the ActionContextThe response is available on the ActionContext instance, which is made available via ThreadLocal.HttpServletResponse response = ServletActionContext.getResponse();Implement ServletResponseAwarePreferredEnsure that servlet-config Interceptor is included in the Action's stack.

o The default stack already includes servlet-config. Edit the Action so that it implements the ServletResponseAware interface.

o The ServletResponseAware interface expects a setServletResponse method. You may wish to include a companion getServletResponse method.

At runtime, call getServletResponse to obtain a reference to the response object.

When the servlet-config Interceptor sees that an Action implements ServletResponseAware, it passes a reference to the request the Action's setServletResponse method.

It is more difficult to test Actions with runtime dependencies on HttpServletReponse. Only implement ServletResponseAware as a last resort. A better approach to solving a use case involving the response may be with a custom Result Type.

How can we access request parameters passed into an Action Edit Page   Browse Space   Add Page   Add News Added by digi9ten, last edited by Ted Husted on Jul 22, 2006  (view change) You can obtain the request parameters by asking the ActionContext or implementing ParameterAware. Implementing ParameterAware is

Page 18: Interceptors in Struts2

preferred.Ask the ActionContextThe request parameters are available on the ActionContext instance, which is made available via ThreadLocal.Map parameters = ActionContext.getContext().getParameters();Implement ParameterAwarePreferredEnsure that servlet-config Interceptor is included in the Action's stack.

o The default stack already includes servlet-config. Edit the Action so that it implements the ParameterAware interface.

o The ParameterAware interface expects a setParameters method. You may wish to include a companion getParameters method.

At runtime, call getParameters to obtain a Map representing the request parameters.

Map parameters = this.getParameters();

When the servlet-config Interceptor sees that an Action implements ParameterAware, it passes a Map of the request parameters to the Action's setParameters method.

To unit test a ParameterAware Action, create your own Map with the pertinent request parameters and call setParameters as part of the test's setUp method.

How do we access static parameters from an ActionEdit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Jul 22, 2006  (view change) show comment

Static (or pre-defined) parameters can be set to a Map property or to individual JavaBean properties.

Define the parameters to be set by adding the name(s) and value(s) to the action mapping element (in the application's struts.xml.

<action name="myAction" class=" MyAction"> <param name="myStaticParam1">myStaticValue1</param> <param name="myStaticParam2">myStaticValue2</param> <param name="myStaticParam3">myStaticValue3</param> </action>

Ensure that static-params Interceptor is included in the Action's stack. o The default stack already includes static-params.

Edit the Action so that it implements the Parameterizable interface.

Map property

Ensure the Action defines a setParams(Map) method.

The static-params Interceptor will set the defined values to the Map, using the name as the entry key.

Page 19: Interceptors in Struts2

key value myStaticParam1 myStaticValue1 myStaticParam2 myStaticValue2 myStaticParam3 myStaticValue3

JavaBean properties

Ensure that the Action defines JavaBean properties corresponding to the param elements in the action mapping.

The static-params|| Interceptor will set the defined values to each JavaBean property that corresponds to a {{param element.

public String getMyStaticParam1()public void setMyStaticParam1(String myStaticParam1)

public String getMyStaticParam2()public void setMyStaticParam2(String myStaticParam2)

public String getMyStaticParam3()public void setMyStaticParam3(String myStaticParam3)

Can we access an Action's ResultEdit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Jul 22, 2006  (view change)

Yes, you can access the ResultConfig objects before the Action executes, and you can access the final Result object using a PreResultListener.

Accessing the ResultConfig Objects

If you need to work with the set of ResultConfigs before the Action executes, you can use an Interceptor to process the Map returned by getResults.

public class MyInterceptor implements Interceptor { // ... public String intercept(ActionInvocation invocation) throws Exception { Map resultsMap = invocation.getProxy().getConfig().getResults();

// do something with ResultConfig in map

return invocation.invoke(); } // ...}

If you are writing against Java 5, you could use a generic when obtain the map.

Page 20: Interceptors in Struts2

Map<String, ResultConfig> resultsMap = invocation.getProxy().getConfig().getResults();

Adding a PreResultListener

If you need to work with the final Result object before it is executed, you can use an Interceptor to register a PreResultListener. The code example creates a PreResultListener as an anonymous inner class.

public class MyInterceptor implements Interceptor { // ... public String intercept(ActionInvocation invocation) throws Exception {

invocation.addPreResultListener(new PreResultListener() {

public void beforeResult(ActionInvocation invocation, String resultCode) { Map resultsMap = invocation.getProxy().getConfig().getResults(); ResultConfig finalResultConfig = resultsMap.get(resultCode);

// do something interesting with the 'to-be' executed result

}

});

return invocation.invoke(); } // ...}

If you are writing against Java 5, you could use a generic when obtain the map.

Map<String, ResultConfig> resultsMap = invocation.getProxy().getConfig().getResults();

How do I obtain security details (JAAS)Edit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Jul 22, 2006  (view change) show comment

You can obtain the UserPrincipal and other security details by going through the request or implementing PrincipalAware. Implementing PrincipalAware is preferred.

Go Through the Request

First obtain the HttpServletRequest and then obtain the security Principal.

HttpServletRequest request = ServletActionContext.getRequest();String authType = request.getAuthType(); // http or https

Page 21: Interceptors in Struts2

String user = request.getRemoteUser(); // the user principal (in string)Principalprincipal = request.getUserPrincipal(); // get a Principal objectbool isAuth = request.isUserInRole("patrick");

Implement PrincipalAware

Preferred

Ensure that servlet-config Interceptor is included in the Action's stack. o The default stack already includes servlet-config.

Edit the Action so that it implements the PrincipalAware interface. o The PrincipalAware interface expects a

setPrincipalProxy(PrincipalProxy) method. You may wish to include a companion getPrincipalProxy method.

At runtime, use the PrincipalProxy reference to invoke methods such as isUserInRole, getUserPrincipal(), getRemoteUser(), isRequestSecure(), and so forth.

Why isn't our Prepare interceptor being executedEdit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Jul 22, 2006  (view change)

Sometimes the order of the Interceptors makes a difference. In the case of the prepare Interceptor, ensure that it comes before validation on the interceptor-stack.

<interceptor-stack name="myInterceptorStack"> ... <interceptor-ref name="prepare" /> ... <interceptor-ref name="validation" /> ... </interceptor-stack>

The default stack does place the prepare Interceptor before the validation Inteceptor.

How do we upload filesEdit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Jan 28, 2007  (view change)

You can obtain the MultipartRequestWrapper from the ServletActionContext or by utilizing the fileUpload interceptor. The fileUpload interceptor is preferred.

Ask the ServletActionContext

MultipartRequestWrapper multipartRequest = ((MultipartRequestWrapper)ServletActionContext.getRequest())

Page 22: Interceptors in Struts2

The MultipartRequestWrapper provideds access methods such as getFiles, getFile, getContentType, hasErrors, getErrors, and so forth, so that you can process the file uploaded.

Utilize the fileUpload Interceptor

_Preferred_

Ensure that {{fileUpload }} Interceptor is included in the Action's stack. o The default stack already includes {{fileUpload }}.

Ensure that the HTML form sets the enctype and specifies on or more file type inputs.

<form name="myForm" enctype="multipart/form-data"> <input type="file" name="myDoc" value="Browse ..." /> <input type="submit" /> </form>

Ensure that the Action provides one or more fileUpload mutator methods, with names that correspond to name of the file type input.

public void setMyDoc(File myDoc)public void setMyDocContentType(String contentType)public void setMyDocFileName(String filename)

The Action may also provide the corresponding accessor methods.

public File getMyDoc()public ContentType getMyDocContentType()public String getMyDocFileName()

Handling multiple files

When multiple files are uploaded by a form, the files are represented by an array.

Given:

<form name="myForm" enctype="multipart/form-data"> <input type="file" name="myDoc" value="Browse File A ..." /> <input type="file" name="myDoc" value="Browse File B ..." /> <input type="file" name="myDoc" value="Browse File C ..." /> <input type="submit" /> </form>

The Action class can define file handling methods that accept an array.

public void setMyDoc(File[] myDocs)public void setMyDocContentType(String[] contentTypes)public void setMyDocFileName(String[] fileNames)

The uploaded files can be handled by iterating through the appropriate array.

Page 23: Interceptors in Struts2

Extra Information

Property Default struts.multipart.parser Commons FileUpload struts.multipart.saveDir javax.servlet.context.tempdir as defined by container struts.multipart.maxSize Approximately 2M Writing Interceptors

Edit Page   Browse Space   Add Page   Add NewsAdded by Musachy Barroso, last edited by Musachy Barroso on Jul 09, 2007  (view change)

See the Interceptors page for an overview of how interceptors work.

Interceptor interface

Interceptors must implement the com.opensymphony.xwork2.interceptor.Interceptor interface.

Interceptor.javapublic interface Interceptor extends Serializable {

void destroy();

void init();

String intercept(ActionInvocation invocation) throws Exception;}

The init method is called the after interceptor is instantiated and before calling intercept. This is the place to allocate any resources used by the interceptor.

The intercept method is where the interceptor code is written. Just like an action method, intercept returns a result used by Struts to forward the request to another web resource. Calling invoke on the parameter of type ActionInvocation will execute the action (if this is the last interceptor on the stack) or another interceptor.

Keep in mind that invoke will return after the result has been called (eg. after you JSP has been rendered), making it perfect for things like open-session-in-view patterns. If you want to do something before the result gets called, you should implement a PreResultListener.

Overwrite destroy to release resources on application shutdown.

Thread Safety

Interceptors must be thread-safe!

Page 24: Interceptors in Struts2

A Struts 2 Action instance is created for every request and do not need to be thread-safe. Conversely, Interceptors are shared between requests and must be thread-safe .

AbstractInterceptor

The AbstractInterceptor class provides an empty implementation of init and destroy, and can be used if these methods are not going to be implemented.

Mapping

Interceptors are declared using the interceptor element, nested inside the interceptors element. Example from struts-default.xml:

<struts> ...

<package name="struts-default"> <interceptors> <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> ... </interceptors> </package>

...</struts>

Example

Assuming there is an action of type "MyAction", with a setDate(Date) method, this simple interceptor will set the date of the action to the current date:

Interceptor Exampleimport com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class SimpleInterceptor extends AbstractInterceptor {

public String intercept(ActionInvocation invocation) throws Exception { MyAction action = (MyAction)invocation.getAction(); action.setDate(new Date()); return invocation.invoke(); }

Page 25: Interceptors in Struts2

}

Action ChainingEdit Page   Browse Space   Add Page   Add News

Added by jcarreira, last edited by Ted Husted on Feb 12, 2007  (view change)

The framework provides the ability to chain multiple actions into a defined sequence or workflow. This feature works by applying a Chain Result to a given Action, and intercepting its target Action's invocation with a ChainingInterceptor .

Don't Try This at Home

As a rule, Action Chaining is not recommended. First explore other options, such as the Redirect After Post technique.

Chain Result

The Chain Result is a result type that invokes an Action with its own Interceptor Stack and Result. This Interceptor allows an Action to forward requests to a target Action, while propagating the state of the source Action. Below is an example of how to define this sequence.

<package name="public" extends="struts-default"> <!-- Chain creatAccount to login, using the default parameter --> <action name="createAccount" class="..."> <result type="chain">login</result> </action>

<action name="login" class="..."> <!-- Chain to another namespace --> <result type="chain"> <param name="actionName">dashboard</param> <param name="namespace">/secure</param> </result> </action></package>

<package name="secure" extends="struts-default" namespace="/secure"> <action name="dashboard" class="..."> <result>dashboard.jsp</result> </action></package>

Another action mapping in the same namespace (or the default "" namespace) can be executed after this action mapping (see Configuration Files). An optional "namespace" parameter may also be added to specify an action in a different namespace.

Chaining Interceptor

Page 26: Interceptors in Struts2

If you need to copy the properties from your previous Actions in the chain to the current action, you should apply the ChainingInterceptor . The Interceptor will copy the original parameters from the request, and the ValueStack is passed in to the target Action. The source Action is remembered by the ValueStack, allowing the target Action to access the properties of the preceding Action(s) using the ValueStack, and also makes these properties available to the final result of the chain, such as the JSP or Velocity page.

One common use of Action chaining is to provide lookup lists (like for a dropdown list of states). Since these Actions get put on the ValueStack, their properties will be available in the view. This functionality can also be done using the ActionTag to execute an Action from the display page. You may also use the Redirect Action Result to accomplish this.

Result TypesEdit Page   Browse Space   Add Page   Add News

Added by casey, last edited by Philip Luppens on Mar 13, 2007  (view change) show comment

Most use cases can be divided into two phases. First, we need to change or query the application's state, and then we need to present an updated view of the application. The Action class manages the application's state, and the Result Type manages the view.

Predefined Result Types

The framework provides several implementations of the com.opensymphony.xwork2.Result interface, ready to use in your own applications.

Chain Result Used for Action Chaining Dispatcher Result Used for web resource integration, including JSP integration FreeMarker Result Used for FreeMarker integration HttpHeader Result Used to control special HTTP behaviors Redirect Result Used to redirect to another URL (web resource) Redirect Action Result Used to redirect to another action mapping

Stream Result Used to stream an InputStream back to the browser (usually for file downloads)

Velocity Result Used for Velocity integration XSL Result Used for XML/XSLT integration

PlainText Result Used to display the raw content of a particular page (i.e jsp, HTML)

S2PLUGINS:Tiles Result

Used to provide Tiles integration

Optional

JasperReports Plugin Used for JasperReports Tutorial Optional, third-party

Page 27: Interceptors in Struts2

integration plugin

Additional Result Types can be created and plugged into an application by implementing the com.opensymphony.xwork2.Result interface. Custom Result Types might include generating an email or JMS message, generating images, and so forth.

Registering Result Types

All Result Types are plugged in via the Result Configuration.

Chain ResultEdit Page   Browse Space   Add Page   Add News

Added by casey, last edited by Philip Luppens on Feb 10, 2007  (view change) show comment

This result invokes an entire other action, complete with it's own interceptor stack and result.

Parameters actionName (default) - the name of the action that will be chained to namespace - used to determine which namespace the Action is in that we're

chaining. If namespace is null, this defaults to the current namespace method - used to specify another method on target action to be invoked. If null,

this defaults to execute method skipActions - (optional) the list of comma separated action names for the actions

that could be chained to

Examples<package name="public" extends="struts-default"> <!-- Chain creatAccount to login, using the default parameter --> <action name="createAccount" class="..."> <result type="chain">login</result> </action>

<action name="login" class="..."> <!-- Chain to another namespace --> <result type="chain"> <param name="actionName">dashboard</param> <param name="namespace">/secure</param> </result> </action></package>

<package name="secure" extends="struts-default" namespace="/secure"> <action name="dashboard" class="..."> <result>dashboard.jsp</result> </action></package>

Page 28: Interceptors in Struts2

Dispatcher ResultEdit Page   Browse Space   Add Page   Add News

Added by casey, last edited by Ted Husted on Sep 10, 2006  (view change)

Includes or forwards to a view (usually a jsp). Behind the scenes Struts will use a RequestDispatcher, where the target servlet/JSP receives the same request/response objects as the original servlet/JSP. Therefore, you can pass data between them using request.setAttribute() - the Struts action is available.

There are three possible ways the result can be executed:

If we are in the scope of a JSP (a PageContext is available), PageContext's {@link PageContext#include(String) include} method is called.

If there is no PageContext and we're not in any sort of include (there is no "javax.servlet.include.servlet_path" in the request attributes), then a call to {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) forward} is made.

Otherwise, {@link RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse) include} is called.

Parameters

location (default) - the location to go to after execution (ex. jsp). parse - true by default. If set to false, the location param will not be parsed for

Ognl expressions.

Examples

<result name="success" type="dispatcher"> <param name="location">foo.jsp</param></result>

FreeMarker ResultEdit Page   Browse Space   Add Page   Add News

Added by casey, last edited by Ted Husted on Sep 10, 2006  (view change)

Renders a view using the Freemarker template engine.

The FreemarkarManager class configures the template loaders so that the template location can be either

relative to the web root folder. eg /WEB-INF/views/home.ftl a classpath resuorce. eg com/company/web/views/home.ftl

Also see Freemarker Support.

Page 29: Interceptors in Struts2

Parameters

location (default) - the location of the template to process. parse - true by default. If set to false, the location param will not be parsed for

Ognl expressions. contentType - defaults to "text/html" unless specified. writeIfCompleted - false by default, write to stream only if there isn't any error

processing the template. Setting template_exception_handler=rethrow in freemarker.properties will have the same effect.

Examples

<result name="success" type="freemarker">foo.ftl</result>

HttpHeader ResultEdit Page   Browse Space   Add Page   Add News

Added by casey, last edited by Ted Husted on Sep 10, 2006  (view change)

A custom Result type for setting HTTP headers and status by optionally evaluating against the ValueStack. This result can also be used to send and error to the client.

Parameters status - the http servlet response status code that should be set on a response. parse - true by default. If set to false, the headers param will not be parsed for

Ognl expressions. headers - header values. error - the http servlet response error code that should be set on a response. errorMessage - error message to be set on response if 'error' is set.

Examples<result name="success" type="httpheader"> <param name="status">204</param> <param name="headers.a">a custom header value</param> <param name="headers.b">another custom header value</param></result>

<result name="proxyRequired" type="httpheader"> <param name="error">305</param> <param name="errorMessage">this action must be accessed through a prozy</param></result>

Redirect ResultEdit Page   Browse Space   Add Page   Add News

Added by casey, last edited by David H. DeWolf on Dec 01, 2006  (view change)

Calls the {@link HttpServletResponse#sendRedirect(String) sendRedirect} method to the location specified. The response is told to redirect the browser to the specified location (a

Page 30: Interceptors in Struts2

new request from the client). The consequence of doing this means that the action (action instance, action errors, field errors, etc) that was just executed is lost and no longer available. This is because actions are built on a single-thread model. The only way to pass data is through the session or with web parameters (url?name=value) which can be OGNL expressions.

Parameters location (default) - the location to go to after execution. parse - true by default. If set to false, the location param will not be parsed for

Ognl expressions.

This result follows the same rules from StrutsResultSupport.

Examples<result name="success" type="redirect"> <param name="location">foo.jsp</param> <param name="parse">false</param></result>

Redirect Action ResultEdit Page   Browse Space   Add Page   Add News

Added by Patrick Lightbody, last edited by Ted Husted on Sep 04, 2006  (view change)

This result uses the ActionMapper provided by the ActionMapperFactory to redirect the browser to a URL that invokes the specified action and (optional) namespace. This is better than the ServletRedirectResult because it does not require you to encode the URL patterns processed by the ActionMapper in to your struts.xml configuration files. This means you can change your URL patterns at any point and your application will still work. It is strongly recommended that if you are redirecting to another action, you use this result rather than the standard redirect result.

See examples below for an example of how request parameters could be passed in.

See ActionMapper for more details

Parameters actionName (default) - the name of the action that will be redirect to namespace - used to determine which namespace the action is in that we're

redirecting to . If namespace is null, this defaults to the current namespace

Examples<package name="public" extends="struts-default"> <action name="login" class="..."> <!-- Redirect to another namespace --> <result type="redirect-action"> <param name="actionName">dashboard</param>

Page 31: Interceptors in Struts2

<param name="namespace">/secure</param> </result> </action></package>

<package name="secure" extends="struts-default" namespace="/secure"> <-- Redirect to an action in the same namespace --> <action name="dashboard" class="..."> <result>dashboard.jsp</result> <result name="error" type="redirect-action">error</result> </action>

<action name="error" class="..."> <result>error.jsp</result> </action></package>

<package name="passingRequestParameters" extends="struts-default" namespace="/passingRequestParameters"> <-- Pass parameters (reportType, width and height) --> <!-- The redirect-action url generated will be : /genReport/generateReport.action?reportType=pie&width=100&height=100 --> <action name="gatherReportInfo" class="..."> <result name="showReportResult" type="redirect-action"> <param name="actionName">generateReport</param> <param name="namespace">/genReport</param> <param name="reportType">pie</param> <param name="width">100</param> <param name="height">100</param> </result> </action></package>

Stream ResultEdit Page   Browse Space   Add Page   Add News

Added by Patrick Lightbody, last edited by Musachy Barroso on Jan 02, 2007  (view change) show comment

A custom Result type for send raw data (via an InputStream) directly to the HttpServletResponse. Very useful for allowing users to download content.

If you are running your app server under HTTPS and having issues with PDF's or other file streams you should take a look at HTTPS and IE Issues

Parameters contentType - the stream mime-type as sent to the web browser (default =

text/plain). contentLength - the stream length in bytes (the browser displays a progress bar).

Page 32: Interceptors in Struts2

contentDispostion - the content disposition header value for specifing the file name (default = inline, values are typically filename="document.pdf".

inputName - the name of the InputStream property from the chained action (default = inputStream).

bufferSize - the size of the buffer to copy from input to output (default = 1024).

Examples<result name="success" type="stream"> <param name="contentType">image/jpeg</param> <param name="inputName">imageStream</param> <param name="contentDisposition">filename="document.pdf"</param> <param name="bufferSize">1024</param></result>

Apache Struts 2 DocumentationVelocity Result

Edit Page   Browse Space   Add Page   Add NewsAdded by casey, last edited by Ted Husted on Sep 10, 2006  (view change)

Using the Servlet container's JspFactory, this result mocks a JSP execution environment and then displays a Velocity template that will be streamed directly to the servlet output.

Parameters location (default) - the location of the template to process. parse - true by default. If set to false, the location param will not be parsed for

Ognl expressions.

This result follows the same rules from StrutsResultSupport.

Examples<result name="success" type="velocity"> <param name="location">foo.vm</param></result>

XSL ResultEdit Page   Browse Space   Add Page   Add News

Added by casey, last edited by Ted Husted on Sep 10, 2006  (view change)

XSLTResult uses XSLT to transform an action object to XML. The recent version has been specifically modified to deal with Xalan flaws. When using Xalan you may notice that even though you have a very minimal stylesheet like this one

<xsl:template match="/result"> <result/></xsl:template>

Xalan would still iterate through every property of your action and all its descendants.

Page 33: Interceptors in Struts2

If you had double-linked objects, Xalan would work forever analysing an infinite object tree. Even if your stylesheet was not constructed to process them all. It's because the current Xalan eagerly and extensively converts everything to its internal DTM model before further processing.

That's why there's a loop eliminator added that works by indexing every object-property combination during processing. If it notices that some object's property was already walked through, it doesn't go any deeper. Say you have two objects, x and y, with the following properties set (pseudocode):

x.y = y;andy.x = x;action.x=x;

Due to that modification, the resulting XML document based on x would be:

<result> <x> <y/> </x></result>

Without it there would be endless x/y/x/y/x/y/... elements.

The XSLTResult code tries also to deal with the fact that DTM model is built in a manner that children are processed before siblings. The result is that if there is object x that is both set in action's x property, and very deeply under action's a property then it would only appear under a, not under x. That's not what we expect, and that's why XSLTResult allows objects to repeat in various places to some extent.

Sometimes the object mesh is still very dense and you may notice that even though you have a relatively simple stylesheet, execution takes a tremendous amount of time. To help you to deal with that obstacle of Xalan, you may attach regexp filters to elements paths (xpath).

Note: In your .xsl file the root match must be named result. This example will output the username by using getUsername on your action class:

<xsl:template match="result"> <html> <body> Hello <xsl:value-of select="username"/> how are you? </body> </html><xsl:template/>

In the following example the XSLT result would only walk through action's properties without their childs. It would also skip every property that has "hugeCollection" in their

Page 34: Interceptors in Struts2

name. Element's path is first compared to excludingPattern - if it matches it's no longer processed. Then it is compared to matchingPattern and processed only if there's a match.

<result name="success" type="xslt"> <param name="location">foo.xslt</param> <param name="matchingPattern">^/result/[^/*]$</param> <param name="excludingPattern">.*(hugeCollection).*</param></result>

Parameters location (default) - the location to go to after execution. parse - true by default. If set to false, the location param will not be parsed for

Ognl expressions. matchingPattern - Pattern that matches only desired elements, by default it

matches everything. excludingPattern - Pattern that eliminates unwanted elements, by default it

matches none.

struts.properties related configuration:

struts.xslt.nocache - Defaults to false. If set to true, disables stylesheet caching. Good for development, bad for production.

Examples<result name="success" type="xslt"> <param name="location">foo.xslt</param> <param name="matchingPattern">^/result/[^/*]$</param> <param name="excludingPattern">.*(hugeCollection).*</param></result>

PlainText ResultEdit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Sep 03, 2006  (view change)

A result that send the content out as plain text. Usefull typically when needed to display the raw content of a JSP or Html file for example.

Parameters

location (default) = location of the file (jsp/html) to be displayed as plain text. charSet (optional) = character set to be used. This character set will be used to set

the response type (eg. Content-Type=text/plain; charset=UTF-8) and when reading using a Reader. Some example of charSet would be UTF-8, ISO-8859-1 etc.

Examples

Page 35: Interceptors in Struts2

<action name="displayJspRawContent" > <result type="plaintext">/myJspFile.jsp</result></action>

<action name="displayJspRawContent" > <result type="plaintext"> <param name="location">/myJspFile.jsp</param> <param name="charSet">UTF-8</param> </result></action>

DispatcherListenerEdit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Oct 17, 2006  (view change)

Use a DispatcherListener object to execute code when a Dispatcher is initalized or destroyed. A DispatcherListener is an easy way to associate customizable components like a ConfigurationManager with a Dispatcher.

Example

static { Dispatcher.addDispatcherListener(new DispatcherListener() { public void dispatcherInitialized(Dispatcher du) { // do something to Dispatcher after it is initialized eg. du.setConfigurationManager(....); }

public void dispatcherDestroyed(Dispatcher du) { // do some cleanup after Dispatcher is destroyed. } }); }

PreResultListenerEdit Page   Browse Space   Add Page   Add News

Added by tm_jee, last edited by Ted Husted on Feb 12, 2007  (view change)

A PreResultListener can affect an action invocation between the interceptor/action phase and the result phase. Typical uses include switching to a different Result or somehow modifying the Result or Action objects before the Result executes.

Examples

A PreResultListener can be added by an Action or an Interceptor.

By an Action

public class MyAction extends ActionSupport { ... public String execute() throws Exception {

Page 36: Interceptors in Struts2

ActionInvocation invocation = ActionContext.getActionInvocation(); invocation.addPreResultListener(new PreResultListener() { public void beforeResult(ActionInvocation invocation, String resultCode) { // perform operation necessary before Result execution } }); } ... }

By an Interceptor

public class MyInterceptor extends AbstractInterceptor { ... public String intercept(ActionInvocation invocation) throws Exception { invocation.addPreResultListener(new PreResultListener() { public void beforeResult(ActionInvocation invocation, String resultCode) { // perform operation necessary before Result execution } }); } ... }