You are on page 1of 19

Struts2

 A web application framework is a piece of structural software that provides


o Automation of common tasks
o A built-in architectural solution that can be easily inherited by applications implemented
on framework.
Struts2 – MVC:
 Struts2 follows Model-View-Controller pattern.
 MVC pattern provides a separation of concerns that applies well to web applications.
 In Struts2, MVC concerns are applied by action, result and FilterDispatcher respectively.
 MVC variant used in Struts is often referred to as front controller.

Controller Component – FilterDispatcher:

 This means that the front controller is out front and is the first component to act in the
processing.
 The controller’s job is to map requests to actions.
 The role of controller is played by FilterDispatcher in Struts2
 The important object is a servlet filter that inspects each incoming request and determines
which action should handle the request.

Model – Action:

 Struts2 actions serve following roles –


o First, an action is an encapsulation of the calls to the business logic into single unit of
work.
o Second, action servers as locus for data transfer.
o Finally, the action must assist the framework in determining which result should render
the view that’ll be returned in the request’s response.

View – Result:

 View is the presentation component of the MVC pattern.


 Struts2 provides out-of-box support for most common-view technologies – JSP, FreeMarker,
Velocity and XSTL.
Struts2 Architecture:

 When the request arrives, FilterDispatcher selects the appropriate action to handle the request.
 There is a stack of interceptors in front of the action.
 The invocation of action must travel through this stack.
 These interceptors are invoked both before and after the action, though we should note that
they actually fire after the result has executed.
 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.
 ValueStack is a storage area that holds all of the data associated with processing a request.
 Rather than passing the data around, Struts2 keeps it in a convenient, central location –
ValueStack.
 OGNL is an expression language that allows you to reference and manipulate the data on
ValueStack.
 The ActionContext contains all of the data that makes up the context in which an action occurs.
 ActionContext has ValueStack and also includes stuff the framework itself will use internally,
such as request, session, and application maps from Servlet API.

 By default, Struts2 looks for URLs ending in .action, but you can configure the framework to look
for .do (the Struts1.x default extension) or even no extension at all.
 There are two ways declaring architecture – XML based configuration or Java annotations.

<struts>
<package name=”login” namespace=”/login” extends=”struts-default”>
<action name="Login" class="manning.Login">
<result>/AccountPage.jsp</result>
<result name="input">/Login.jsp</result>
</action>
</package>
<struts>
 The framework uses struts.xml as the entry point. The file resides in the Java classpath and must
be created by the developer. While it is possible to declare all your components in struts.xml,
developers more commonly use this file only to include secondary XML files.
 Using annotations:

@Results({
@Result(name="input", value="/RegistrationSuccess.jsp" )
@Result(value="/RegistrationSuccess.jsp" )
})
public class Login implements Action {
public String execute() {
//Business logic for login
}
}
 Many commonly used Struts2 components do not need to be declared by the developers. These
predefined components are the part of Struts2 intelligent defaults. These components are
declares in struts-default.xml, found in struts2-core.jar.
 Web.xml of the webapp:

<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>manning</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

 actionPackages parameters is necessary if you are going to use annotations in your package.
 struts.xml

<struts>
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<action name="Menu">
<result>/menu/Menu.jsp</result>
</action>
</package>
<include file="manning/chapterTwo/chapterTwo.xml"/>
<include file="manning/chapterThree/chapterThree.xml"/>
...
<include file="manning/chapterEight/chapterEight.xml"/>
</struts>
o Constant element can be used to set framework properties. You can also do this with
property files.
o struts.xml is a good place to define global actions in default package.
o Include element can be used to pull xml files into declarative architecture.
 While many Struts2 actions will implement the Action interface, they are only obligated to meet
an informal contract.
 The execute() method contains business logic and returns a string that indicates which of its
results should render the result page.
 Domain data is always stored in the action. This is because it allows convenient access to data
from action’s execute() method.
 So that the rest of the framework can access data, the action object is itself placed in the
ValueStack.
 The mechanics of ValueStack are such that all properties of the action will then be exposed as
top level properties of ValueStack.

Actions:
 Struts2 creates a new instance of action for every request.
 Actions and other components can be grouped together into packages. These packages are
similar to Java packages.
 You can set following attributes in the package:

Name (required) Name of the package


Namespace Namespace for all actions in package
Extends Parent package to inherit from
Abstract If true, this package will only be used to define
inheritable components, not actions

 Note that you can give the same namespace to more than one packages.
 If you don’t set the namespace attribute, your actions will go into the default namespace. The
default namespace sits beneath all of the other namespaces waiting to resolve requests that
don’t match any explicit namespace.
 Note that the default namespace is actually the empty string “”. You can define a root
namespace such as “/”. The root namespace is treated as all other explicit namespaces and must
be matched.
 Most actions implement com.opensymphony.xworks2.Action which defines only
String execute() throws Exception method. It also defines some string constants like ERROR,
INPUT, LOGIN etc.,
 ActionSupport class is a convenience class that provides default implementation of Action
interface and several other useful interfaces. If your action class extends this class, they
automatically gain the use of default implementations of several important interfaces.
 Action Support provides a quick form of basic validation.
 This class works with workflow interceptor to perform basic validation.
 When workflow interceptor fires, it will look for validate() method on the action (through
com.opensymphony.xwork2.Validateable interface).
 If the piece of data doesn’t validate, we create and store an error via methods provided by the
ActionSupport superclass, such as addFieldError() or addActionError().
 After all validation logic has executed, control returns to workflow interceptor. The workflow
interceptor will check to see whether any error messages were generated by validation logic.
Workflow interceptor will abort the request processing and return the user back to input form.
Using Resource Bundles for message text:

 Getting started with resource bundle properties file is easy.


 First, we need to create the properties file and give it a name that mirrors action class for which
it provides the messages.
 Add the properties file to the package that contains the action class.
 com.opensymphony.xwork2.TextProvider interface provides access to the messages itself.
 ActionSupport class implements this interface.
 Use TextProvider’s getText() method to retrieve messages from property files based on the key.
 ActionSupport also implements LocalProvider interface’s only method getLocale(). This default
implementation of the method retrieves locale from the browser settings.
 Struts uses getText() method to get messages from appropriate properties file for specific locale.

Data transfer:

 There are three ways of transferring data.


 One, the params interceptor included in the defaultStack automatically transfers data from the
request to our action objects. To enable this transfer, the developer needs only to provide
JavaBean properties on the action, using the same name as form fields being submitted.
 Two, use an application domain object as a JavaBean property in the action class. But, when you
access the properties, we have to reflect the depth of property in action.
 Three, ModelDriven – ModelDriven action departs from use of JavaBean properties for exposing
domain data. Instead, they expose an application domain object via getModel() method of
ModelDriven interface.
o We have to have our action implement ModelDriven interface.

private User user = new User();


public Object getModel() {
return user;
}
o We HAVE to initialize the object ourselves.
o Override getModel() that returns our model object.
o We don’t incur depth of penalty in our view layer (as we did in method Two).

File Upload:

 Struts2 provides built-in support for file upload.


 Default interceptor stack includes the FileUploadInterceptor.
 When fileUploadInterceptor executes, it processes a multipart request and transforms the file
itself along with some metadata, into request parameters.
[file name from form] File—the uploaded file itself
[file name from form]ContentType String—the content type of the file
[file name from form]FileName String—the name of the uploaded file,
as stored on the server
 We have to set the encoding type of the form to multipart/form-data. Without this setting it
won’t work.

<s:form action="ImageUpload" method="post" enctype="multipart/form-data">

Interceptors:

 Interceptors remove cross-cutting tasks from our action components.


 Some of the tasks undertaken by interceptors are more easily understood as being
preprocessing or postprocessing tasks.
 In Struts2, no action is invoked in isolation.
 The invocation of an action is a layered process that always includes the execution of a stack of
interceptors prior to and after the actual execution of action itself.
 Rather than invoke the action’s execute() method directly, the framework creates an object
called an ActionInvocation that encapsulates the action and all of the interceptors that have
been configured to fire before and after the action executes.
 Invocation of an action must first travel through the stack of interceptors associated with the
action.
 The action will ultimately execute and return a control string that selects the appropriate result.
 After the result executes, each of the interceptors, in reverse order, gets a chance to do some
postprocessing work.
 One of the powerful functional aspects of interceptors is their ability to alter workflow of
invocation.
 When the framework receives a request, it first must decide to which action the URL maps. An
instance of this is added to a newly created instance of ActionInvocation. Next, references of the
interceptors that need to fire are added to ActionInvocation. In addition, the ActionInvocation
also holds references to other important information like the servlet request object and a map
of the results available to the action.
 The ActionInvocation exposes the invoke() method, which is called by the framework to start
the execution of action.
 ActionInvocation keeps track of what stage the invocation process has reached and pass control
to appropriate interceptor in the stack.
 It does this by calling interceptor’s intercept() method.
 An interceptor has a three-stage, conditional execution cycle:
o Do some preprocessing.
o Pass control to the successive interceptors, and ultimately the action, by calling the
invoke(), or divert execution by itself returning a control string.
o Do some postprocessing
 Static-params interceptor

<action name="exampleAction" class="example.ExampleAction">


<param name="firstName">John</param>
<param name="lastName">Doe</param>
</action>

 Servlet-Config Interceptor:
o The servlet-config interceptor provides a clean way of injecting various objects from the
Servlet API into your actions.
o This interceptor works by setting the various objects on setter methods exposed by
interfaces that action must implement.
o Following interfaces are available for retrieving various objects related to servlet
environment:
ServletContextAware – ServletContext
ServletRequestAware – ServletRequest
ServletResponseAware – ServletResponse
ParameterAware – Sets a map of request parameters
RequestAware – sets a map of request attributes
SessionAware – sets a map of the session attributes
ApplicationAware – sets a map of application aware attributes
PrincipalAware – Sets the principal object
o Each of these interfaces contains one method – a setter – for resource in question.
 Prepare Interceptor:
o When prepare interceptor fires, it looks for prepare() method (and if your action
implements preparable interface). If your action is preparabale, prepare() method is
executed. This allows for any sort of preprocessing to occur.
 Exception Interceptor
 Token and Token-session Interceptors:
o These interceptors can be used as a part of the system to prevent duplicate form
submission.
 ExecAndWait Interceptor

<package name="struts-default">
<interceptors>
<interceptor name="execAndWait" class="ExecuteAndWaitInterceptor"/>
<interceptor name="exception" class="ExceptionMappingInterceptor"/>
<interceptor name="fileUpload" class="FileUploadInterceptor"/>
…..
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servlet-config"/>
</interceptor-stack>

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

 Interceptor declaration must be contained in a package element.


 <interceptors> element contains all the <Interceptor> and <interceptor-stack> declaration of
the package. A package can declare a default set of interceptors.

public class AuthenticationInterceptor implements Interceptor {


public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation actionInvocation )
throws Exception{
Map session = actionInvocation.getInvocationContext().getSession();
User user = (User) session.get( Struts2PortfolioConstants.USER );
if (user == null) {
return Action.LOGIN;
}
else {
Action action = ( Action ) actionInvocation.getAction();
if (action instanceof UserAware) {
((UserAware)action).setUser(user);
}
return actionInvocation.invoke(); --- continue action invocation
}
}
}

OGNL

 OGNL is the default expression language of Struts2.


 OGNL – Object Graph Navigation Language.
 ValueStack holds a stack of objects. These objects all have properties. The magic of ValueStack is
that all properties of these objects appear as properties of ValueStack itself.
 Action object is also placed on ValueStack and all the properties of the action are exposed as
properties of ValueStack.
 If there are two objects with same property on the ValueStack, the property of the higher object
in the stack cover up similarly named properties of lower in stack.
 When result starts its rendering process, it’ll also have access to ValueStack via OGNL expression
language in its tags. These tags will retrieve data from ValueStack by referencing specific values
with OGNL expressions.
 Struts2 comes with built-in support for converting between HTTP native strings to following Java
types: String, Boolean/Boolean, char/Character, int/Integer, float/Float, long/Long,
double/Double, Date (SHORT format), array (each string must be convertible to array type),
List and Map (both populated by Strings by default).
 Transferring data into array-
o Three properties named age – OGNL creates a new array and transfers the data into
array.
o Three individual parameters with names that look like array indexing – We have to
initialize the array.
 You don’t have to pre initialize the list, even the ones that receive data from the index OGNL
notation.
 With type specification, elements of the list will all be String objects.
 Without type specification, the elements will all be String objects.
 Properties file can be used to specify what type of element we want in our List property. Use
Actionclassname-conversion.properties and specify in properties file -> Element-
elementname=java.lang.Double. Don’t pre initialize the List when using this method.
 To work with maps,

<s:textfield name="maidenNames.mary" label="Maiden Name"/>


Or
<s:textfield name="maidenNames['beth']" label="Maiden Name"/>

 We can implement customized type convertors. Just make a class extend StrutsTypeConvertor
and implement two methods convertFromString() and convertToString().

ActionContext

 We already know that our action is placed on ValueStack. ValueStack itself is store in something
called ActionContext.
 We know that OGNL targets objects on ValueStack.
 In reality, OGNL expressions can resolve against any set of objects. ValueStack is one among
them and the default one.
 The ActionContext contains all of the data available to the framework’s processing of the
request, including things ranging from application data to session or application scoped maps.
All of the application specific data will be held in ValueStack.
 The other objects on ActionContext are all maps of important sets of data.

Parameters Map of request parameters for this request


Request Map of request-scoped attributes
Session Map of session-scoped attributes
Application Map of application-scoped attributes
Attr Returns first occurrence of attribute occurring
in the page, request, session or application
scope.
ValueStack Contains all the application-domain-specific
data for the request
 By default, ValueStack will serve as the root object for resolving all OGNL expressions
that don’t explicitly don’t name an initial object.
 The # operator tells OGNL to use named object, located in its context, as the initial
object for resolving the rest of the expression. #session[‘user’]
 Accessing an array or list : array[0], array.length, list.isEmpty
 Creating a list {1,2,3}
 map[‘foo’], map.foo, map.size, map.isEmpty
 creating maps dynamically - #{“foo”:”bar”, “abc”:”xyz”}

Struts2 Tags:

 Strut2 tag API provides functionality to dynamically create robust web pages.
 Struts2 comes with data tags, control-flow tags, UI and miscellaneous tags.
 Data tags focus on ways to extract data from the ValueStack and/or set values in the ValueStack.
 If the attribute is of type String, then the value written into the attribute, in the actual JSP page
is interpreted as a String literal. If an attribute is some non-string type, then value written into
the attribute is interpreted as an OGNL expression.
 You can force a string attribute to be interpreted as an OGNL expression using the %
{expression}. JSTL EL ${expression}
 Data Tags:
o Property Tag – Used for writing a property into the rendering HTML.
<s:property value="user.username"/>.
o Set Tag – Used to assign a property to another name.
<s:set name="username" value="user.username"/>
Can specify scope – application, session, request, page or action. Default action. i.e,
you can access the property now as #username.
o Push Tag – Allows you to push properties onto the ValueStack.
o Bean Tag – is like a hybrid of set and push. You can create an instance of object and
push it to ValueStack. The value will remain on the ValueStack for the duration of the
tag.
Now we will see how we can do the same by creating a top-level reference to the bean
in theActionContext. We do this using the following code.

<s:bean name="vaannila.CurrencyConverter" var="converter">
<s:param name="dollars" value="100"></s:param>
</s:bean>
Dollars = <s:property value="#converter.rupees" /> Rupees
o Action tag – To invoke another action from view layer.
 Control Tag
o Iterator tag <s:iterator value="songs" status="songStatus">
o If and else tags
 URL tag can be used to automatically persist session in absence of cookies.
 Text tag – Is used to retrieve language specific text from resource bundles.
 I18n tag – used to set resource bundle. Resource Bundle is used only for duration of the tag.

Results
 As an alternative to configuring results locally to specific actions, you can also configure results
globally – for an entire package.
 When an action returns a control string, the framework consults the set of results as defined
locally to action. If no results with the name are found, it then consults the globally defined set
of results.
 Note, locally defined results will override a globally defined results during the lookup process

<global-results>
<result name="error">/chapterFour/Error.jsp</result>
</global-results>

 Commonly defined result types: dispatcher, redirect, redirectAction


Validation Framework

 One of the strong points of validation framework is the Validator, a reusable component in
which the logic of specific types of validations is implemented.
 There are three main components of validation framework:
o Domain data – Data to validate
o Validation Metadata – used to associate individual data properties with validators
o Validators – Actual validation is performed here
 Validation interface also makes use of ValidationAware interface to store errors and the
workflow interceptor to route back to input page, if necessary.
 One more interceptor, Validation Interceptor, is used as the entry point of validation
framework.
 You can use basic validation and validation framework together. When you use defaultStack,
both the validation and workflow interceptors fire. First, the validation interceptor runs all
validations that you define with the validation framework metadata. Then, when the workflow
interceptor runs, it still checks to see if your action implements the validate() method. When the
second phase of workflow interceptor checks for errors, it doesn’t care or knows who created
them. The effect is same.
 Validation metadata must be placed in a XML file named actionclassname-validations.xml and
placed in the package next to the action class.

<validators>
<field name="username">
<field-validator type="stringLength">
<param name="maxLength">8</param>
<param name="minLength">5</param>
<message>
While ${username} is a nice name, a valid username must
be between ${minLength} and ${maxLength} characters long.
</message>
</field-validator>
</field>

<field name="email">
<field-validator type="requiredstring">
<message>You must enter a value for email.</message>
</field-validator>
<field-validator type="email">
<message key="email.invalid"/>
</field-validator>
</field>
<validator type="expression">
<param name="expression">username != password</param>
<message>Username and password can't be the same.</message>
</validator>
</validators>

 Field validators are validators that operate on individual fields.


 We need to put <field-validator> element inside <field> to declare which validators
should validate this piece of data.
 Any number of validators can be declared.
 <message> element contains the text of error message.
 You can also declare non-field validators that don’t apply logic targeted at a specific
field.
 These validators apply to the whole action and often involve more than one field value.
 The built-in validators only offer one instance of a non-field validator: the expression
validator.
 This useful validator allows you to embed an OGNL expression that contains the logic of
the validation you wish to perform.
 Here too, OGNL resolves against ValueStack.
 OGNL in these XML files uses $ instead of % that’s normally used.
 We can externalize the message into resource bundle.

Writing a custom validator:

 All validators are obligated to implement the Validator or FieldValidator interface.


 Framework provides two convenience classes, ValidatorSupport and
FieldValidatorSupport

public class PasswordIntegrityValidator extends FieldValidatorSupport {

public void validate(Object object) throws ValidationException {


String fieldName = getFieldName();
String fieldValue = (String) getFieldValue(fieldName, object );
getSpecialCharacters();

if ( !digitMatcher.find() ) {
addFieldError( fieldName, object );
}
}
private String specialCharacters;
//Getter and setter omitted
}
 The logic is placed in the validate() method
 Developer must create all JavaBean properties to match all the parameters that should
be exposed to the user.

<field-validator type="passwordintegrity">
<param name="specialCharacters">$!@#?</param>
<message>
Your password must contain one letter, one number, and one of
the following "${specialCharacters}".
</message>
</field-validator>
 We declare our own custom validators in an application local validators.xml file and
place it in the root of our classpath.

<validators>
<validator name="passwordintegrity"
class="manning.utils.PasswordIntegrityValidator"/>
</validators>

 Short-circuiting validations:
<field-validator type="stringlength" short-circuit="true">
If validation performed by this validator fails, further validators declared for the field are
not performed.

 Form, validate=”true” – clientside validation.

Internationalization
 Java support for internationalization centers around two classes from java.util package –
ResourceBundle and Locale.
 ResourceBundle is a locale-sensitive object.
 The resources that are found in these ResourceBundles are message texts.
 ResourceBundle is an abstract class. Subclasses of ResourceBundle can manage their
resources in any way they want.
 Most commonly used subclass is PropertyResourceBundle, which loads its resources
from plain text properties file.
 We should create one properties file for each language-specific version of the text
resource.
 Regardless of the number of supported locales, all of the properties files that share the
same root bundle name belong to a single bundle.
 Java native code for working with resource bundles:

Locale currentLocale = new Locale( "tr");


ResourceBundle myMessages =
ResourceBundle.getBundle("EmailClientMessages",currentLocale);
String greetingLabel = myMessages.getString( "greeting");

 How does getBundle() method know which properties file to use – First, it searches for Java
properties file that matches the bundle name parameter that it receives. After that, it also
searches for Java class implementation of the bundle.

 Struts2 still uses above classes, but it makes things easier.


 Struts2 automatically creates ResourceBundles for you, handling the whole mess of
determining which bundles you need.
 TextProvider interface exposes an overloaded method getText(). TextProvider takes your
key and tracks down an associated message text from ResourceBundles that it knows about.
 The helper class ActionSupport provides default implementation of TextProvider.
 If your action extends ActionSupport, framework pushes TextProvider onto the ValueStack.
 Default implementation of TextProvider loads the ResourceBundles that have names
matching the current action, as well as several others.
 Here are the steps you need to follow:
o Make your action implement ActionSupport.
o Put some properties files somewhere they can be found by default implementation
of TextProvider.
o Start pulling messages into your pages with text tag or by hitting the getText()
method with direct OGNL.
 Default TextProvider ResourceBundle location algorithm:
o ActionClass – Is there a ResourceBundle with same name as the action class?
o MyInterface – If your action implements any interfaces, are there ResourceBundles
associated with those interfaces? It looks for properties file with name
MyInterfacename.properties.
Superinterfaces of each interface will also be searched accordingly, with more
specific interfaces taking precedence over superinterface.
o MySuperClass – If your action extends a superclass, is there a ResourceBundle
associated with the superclass?
It looks for MySuperClass.properties if the superclass is named MySuperClass.
Note the search continues up the superclass chain all the way to Object.
ResourceBundles of classes lower on chain take precedence over the higher ones,
i.e Object.properties comes last.
o If the action implements ModelDriven, the class of the model object itself will be
used to look up ResourceBundles. If our model is User.java, then framework looks
for User.properties and the entire process of searching interfaces and superclasses
is followed.
o package.properties – If our current action is manning.chapter11.PHome, the
framework will attempt to find a package.properties in manning.chapter11 package
and then in manning package.
o Domain model object exposed on ValueStack referenced by key - This is similar to
#4, ModelDriven. Given a key such as user.username, if the ValueStack has a
property exposed on it named user, then the class of that property will be used to
load ResourceBundles, again following the same process we’ve outlined. However,
when resolving the key against those bundles, the first element of the key is
stripped away. In other words, given the key user.username, and a user property on
the ValueStack (of type User), the ResourceBundles associated with User, beginning
with the User.properties, will be searched for a message with the key username, not
user.username.
o DefaultResourceBundles – Struts2 allows you to specify global bundles that will
always be available.
 Remember, locale specificity only matters within the bounds of a given resource bundle. For
ex, between MyInterface.properties and MySuperclass_en_US.properties,
MyInterface.properties takes precedence.
 Defining Default Bundles
o In order to have Struts2 find your properties files, you must put them where it
wants them.
o The framework does however provide you with a way to locate your properties file
according to your own whim. This is the role of default bundles.
o This is the last place framework will look to resolve a key.
o Default bundles can in fact, be thought as global bundles.
o To tell the name of the default bundle to the framework, you just need to set
struts.custom.i18n.resources property.
o You can set this in struts.properties file or with a constant element in one of your
configuration files.

struts.custom.i18n.resources=global-messages,manning.utils.otherBundle

 Retrieving messages from you bundles:


o text tag
o getText() in OGNL
o key attribute of UI component tags
o key element of message element in validation metadata XML file.
 Use i18n tag to specify a ResourceBundle for the body of the tag.
 You can parameterize your message text with OGNL. But remember to use $ as escape
sequence instead of %.
 Always provide your default language message text in default resource bundle. Default
resource bundles are named xxxx.properties, with no suffix of locale. There must be a
default bundle to fall back on if requested locale isn’t supported.

 Framework automatically determines default locale at the start of the request processing.
 This determination is made from the HTTP header in the request.
 The i18n interceptor checks to see if the request contains a parameter named
request_locale. If this parameter exists in the request, then this value is set on
ActionContext, thus overriding the default locale choice made by the framework.
 You can use this parameter to have user select a locale interactively.
 As ActionContext exists for a single request, when user sets the request_locale parameter
once, i18n interceptor will store it in session scoped attribute named,
WW_TRANS_I18N_LOCALE.

DispatchAction functionality – Dynamic method dispatch

 In Struts 1 DispatchAction helps us in grouping a set of related functions into a single action. In
Struts 2 all the Actions by default provide this functionality. To use this functionality we need to
create different methods with the similar signature of the execute() method, only the name of
the method changes.
 We need to specify which method in the action class will be called while configuring the action
mapping. A separate action mapping needs to be created for each method in the action class.
The following action mapping is done in the struts.xml file.

<action name="addUser" method="add" class="vaannila.UserAction">


<result name="success">/success.jsp</result>
</action>
{If you have n methods in the action class, you configure n actions.}
Dynamic method invocation – instead configure just one action.
<action name="*User" method="{1}" class="vaannila.UserAction">
<result name="success">/success.jsp</result>
</action

As you can see we have replaced all the method names with an asterisk symbol. The word that
matches for the first asterisk will be substituted for the method attribute. So when the request
URL is "addUser" the add() method in the UserAction class will be invoked. Method name will be
submitted for {1}.
Using tokens to prevent duplicate form submits

- Prepare the web page with a unique token embedded as a hidden field.
- Stash this unique token in the user session.
- Return the page to user browser.
- When the form is submitted, the two tokens are compared.
- If the tokens do not match, invalid.token result is returned.

<s:form>
<s:token/>
<s:textfield key="coinToss"/>
<s:submit action="flipCoin"/>
</s:form>

<action name="flipCoin" method="flipCoin" class="CoinAction">


<interceptor-ref name="tokenStack"/>
<result name="success">samplesPage</result>
<result name="invalid.token">duplicatePage</result>
</action>

Displaying wait pages automatically

 Interceptor stack for long running action

<interceptor-stack name="waitStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="execAndWait" />
</interceptor-stack>

 Note that the execAndWait interceptor is declared last. It’s important that execAndWait be the
last interceptor, because it stops the execution and no further interceptors will be called. In the
thread created by the execAndWait interceptor, only the action is executed, so any interceptors
after the execAndWait will never be run.

<action name="search" class="SearchAction">


<interceptor-ref name="waitStack"/>
<result name="success">resultsPage</result>
<result name="wait">waitPage</result>
</action>

 The most interesting element of the web page is the meta tag in the head section. This instructs
the web browser to rerequest the URL that resulted in this wait page every two seconds. As long
as the processing of the action is going on, the waitPage view is returned, which sets the
browser timer to refresh again in two seconds. Eventually, the action finishes and a page refresh
returns the result from the action by rendering the resultsPage in the browser.

<html>
<head>
<title>Please wait</title>
<meta http-equiv="refresh" content="2;url=<s:url/>"/>
</head>
<body>
Processing your request. Please wait a moment...
</body>
</html>

You might also like