Struts2 0document
Struts2 0document
0
• Struts is web application framework which will be used to develop the web-based applications fastly
and easily.
• Struts is a web application framework implemented by Apache and OpenSymphony.
• It is implemented based on two existing framework Apache struts 1.0 and OpenSymphony webwork.
• New features in struts 2
1. Interceptors – For applying cross cutting concerns.
2. Annotations – For reducing XML configuration.
3. OGNL – For accessing the data from any part of the framework.
4. New set of tag libraries.
• Struts 2.0 supports two types of configuration
1. XML based configuration.
2. Annotation based configuration.
• Like strut 1.x, JSF, Spring MVC, struts 2.0 is also implemented based on two well known design
patterns called Front Controller and MVC design pattern.
Description of the problem: Always system requires a centralized access point for request handling.
Without centralized access point, code that is common across multiple requests are duplicated in
various places. This gives you code duplication problem, because of this maintenance will be
increased.
Solution: Use the Front Controller as the initial point of contact for handling all the requests. Front
Controller centralizes controller logic and avoids the code duplication problem.
2. MVC design pattern(Model, View and Controller) :- is used for decoupling business, controller and
presentation logic.
In struts 2, it is implemented by action, JSP and FilterDispatcher.
1) Controller – FilterDispatcher
The role of the controller is played by FilterDispatcher.
The controller’s job is to map requests to actions.
You just need to inform the framework which request URL maps to which of your
actions. You can do this with XML based configuration files, or with Java annotations.
2) Model– Action
Model is the application logic and contains both data and business logic.
3) View – JSP
This page is the user interface which presents a representation of the application’s state
to the user.
Because of MVC design pattern we have 3 layers in struts based application.
I. Presentation Layer.
II. Controller Layer.
III. Model Layer.
Note: OGNL targets ValueStack as the default object for accessing or processing values. If any value
is required from any other object then we should explicitly specify the map object name.
<html>
<body bgcolor="orange">
<s:form action="cluster/doLogin" method="GET">
</body>
</html>
2) in url request
3) in struts.xml file
<struts>
<package name="action" namespace="/cluster" extends="struts-default">
<action name="doLogin" class="com.cluster.action.CheckUser" >
<result name="failure">/jsp/loginFailure.jsp</result>
<result name="success">/jsp/loginSuccess.jsp</result>
</action>
</package>
</struts>
1. Upon receiving the request , FilterDispatcher takes the package namespace associated with the
current url request and verifies in the struts.xml file.
2. If namespace is not found with the current url then FilterDispatcher tries to process previous
request package namespace.
3. If that also not found then errors will be given to client.
4. If package namespace found, then that package will be verified to find the action with the action
name which is associated with the current request.
5. If action is not found in the package then error message will be given to client.
6. If action is found then action class will be taken and its life cycle will be started.
• Following are the various components of struts 2 framework and their corresponding roles.
1. FilterDispatcher
3. Actions.
• Action class contains both data and business logic and is always placed inside the ValueStack.
• Action will always do three things.
1) It contains the logic to be executed for a particular request.
2) It stores and carries the data so that we can access the data from the request till the view.
3) It decides the view for a particular request.
• The Action serves as a centralized data transfer object that can be used to make the application data
available in all tiers of the framework.
• The use of Actions as data transfer objects should probably ring some alarms in the minds of alert
Struts 1 developers. In Struts 1, the action classes were singletons i.e. there is only one instance of
the Action class.
In a multi-threaded environment, such as a web application, it would be very problematic to store
data as instance fields in the Action class.
• But struts 2 solves this problem by creating a new instance of an action for each request that maps
to it. This allows Struts 2 objects to exist as dedicated data transfer objects for each request.
• Even if we are concerned about the performance issue because a new action object is created for
every request, just consider the fact that even with a singleton action object we still would
have to create some sort of data transfer object for the request. So, object instantiation is
certainly not higher in Struts 2.
4. ActionContext.
• The ActionContext holds all the important data objects related to a given action invocation and
OGNL can target any of them.
• Following are the different objects of ActionContext.
Name Description
1) Parameters Map of request parameters.
2) Request Map of request attributes.
3) Session Map of session attributes.
4) Application Map of context attributes.
5) Attr Gives value of an attribute starting from page, request, session or
application.
6) ValueStack Contains the Action class object (properties or data of the action class)
and domain data (Model data)
5. ValueStack.
#session.STRNAME
or
#session[‘STRNAME’]
Here OGNL tries to resolve the value from session map object.
7. Results.
• This is the jsp or the user interface which presents a representation of the application’s state to the
user.
• We can use the struts 2 tag libraries here for displaying the jsps.
• The struts 2 tag libraries are divided into two groups general purpose tags and UI component tags.
General purpose tags provide support for all sort of things from conditional logic to ValueStack
manipulation, etc.
The UI component tags generate only HTML form fields.
8. ActionInvocation
• Whenever a request is received the FilterDispatcher creates an object of ActionInvocation which
encapsulates the Action, all of the interceptors and the result which has to be executed for a
particular request.
What is struts-default value in the <package> tag and why does the developer extend it?
• Many of the predefined components are declared in struts-default.xml, found in struts2-core.jar.
• This xml file contains the struts-default package. (This package contains defaultStack)
• The developer generally extends this package to reuse the built in components of the framework.
When we do not extend this package, we are rejecting many features of the framework. The struts-
default package, defined in the struts-default.xml, contains all the commonly needed Struts 2
components ranging from complete interceptor stacks to all the common result types. Most of the
interceptors that we use are found in the struts-default package which is in the struts-default.xml file.
• By not extending the struts-default we would be losing lots of functionality of the struts framework.
• Struts 2 API has one main interface and one class.
1)
public interface Action {
public static final String ERROR = "error";
public static final String INPUT = "input";
public static final String LOGIN = "login";
public static final String NONE = "none";
public static final String SUCCESS = "success";
String execute();
}
When our action class implements Action interface then we are unable to make use of struts 2
existing functionality like validation, internationalization, accessing message bundles etc.
String execute();
addActionError(String anerrormessage);
addFieldError(String fieldname, String errormessage);
getText(String textname);
validate();
}
When our action class extends ActionSupport then we get lots of functionality like validation,
internationalization, accessing message bundles etc.
• This is considered to be the best approach since we get most of the features of the framework like
validation, internationalization, accessing message bundles etc.
UserTO userTO;
//userTO = new UserTO(); 1st way
public void prepare() throws Exception { //2nd way
System.out.println("Inside prepare()");
userTO = new UserTO();
}
• The advantage of using ModelDriven action approach is we can now access the values in a simpler
way and there is no deeper access notation.
Step 1 ) Write a properties file with key and value pairs as follows.
<constant name="struts.custom.i18n.resources"
value="MyApp.ApplicationResources_hi" />
<constant name="struts.custom.i18n.resources"
value="MyApp.ApplicationResources_kn" />
Step 1: Your action also must extend ActionSupport class and you must override validate() method
in your action class.
a) Verify the client submitted data to check whether it is following the given validation rules or not.
b) If not following, invoke the addFieldError() method with field name and the key specified in the
property file or type the message.
<result name="input">/jsp/login.jsp</result>
Step 3) Write the error message in the property file with the corresponding key
login.password.required= Please enter your Password
• When we are developing any web based application we need to perform the validation in client
submitted data.
• Already we have seen the way to implement validations by overriding the validate() method in the
action class.
• validate() method has the following limitations:-
1. Developer is responsible to write the validation code inside the validate() method for all action
classes.
2. Sometimes you may write the same validation code in multiple validate methods belonging to
multiple action classes. This gives code duplication problem.
<html>
<body bgcolor="lightblue">
<s:form action="doLogin" method="GET">
<s:textfield name="username" key="login.username"/>
<s:submit method ="execute" key="login.login"/>
</s:form>
</body>
</html>
Step 2: Write the required validation in the validation.xml file. The naming convention of the xml file is
ActionClass-validation.xml file. (Eg: CheckUser-validation.xml). This xml file should be placed in package
directory structure of the action class itself.
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="login.name.required"></message>
</field-validator>
</field>
</validators>
Step 3: Your action configuration should have a result with name input (strus-config file). This is the page
which gets displayed if validation fails.
<result name="input">/jsp/login.jsp</result>
Step 4: Write the error message in the property file with the corresponding key
Note: We use short-circuit = “true” attribute in the <field-validator> tag for short
circuiting the validations i.e. if the first validation fails then second will not be applied.
<html>
<body bgcolor="lightblue">
<s:form action="doLogin" method="GET">
<s:textfield name="username" key="login.username"/>
<s:submit method ="execute" key="login.login"/>
</s:form>
</body>
</html>
Step 2: Write the required validation in the Action class itself. The validations should be applied at setter
methods of the field.
Step 3: Your action configuration should have a result with name input (strus-config file). This is the page
which gets displayed if validation fails.
<result name="input">/jsp/login.jsp</result>
Step 4: Write the error message in the property file with the corresponding key
<html>
<body bgcolor="lightblue">
<s:form action="doLogin" method="GET">
<s:textfield name="username" key="login.username"/>
<s:submit method ="execute" key="login.login"/>
</s:form>
</body>
</html>
Step 2: Write a validation.xml file for the action class but this will not contain any validation logic. It will
only contain the code to delegate the validation to the domain object or TO’s validation.xml file. This is
done with the help of “visitor” validator. The naming convention of the xml file is ActionClass-
validation.xml file. (Eg: CheckUser-validation.xml). This xml file should be placed in package directory
structure of the action class itself.
<validators>
<field name="model">
<field-validator type="visitor">
<param name="appendPrefix">false</param>
<message>Hello</message>
</field-validator>
</field>
</validators>
Step 3: Write another validation.xml file which contains the validation logic. This file should be placed in
package directory structure of the TO or domain object. The naming convention of this file will be -
TOname-validation.xml (Eg: CheckUserTO-validation.xml)
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="login.name.required"></message>
</field-validator>
</field>
</validators>
Step 4: Your action configuration should have a result with name input (struts-config file). This is the
page which gets displayed if validation fails.
<result name="input">/jsp/login.jsp</result>
Step 5: Write the error message in the property file with the corresponding key
4. Register your custom validator by writing the validator tag inside the validators.xml. This
validators.xml file must be under src folder.
<validators>
<validator name="passwordintegrity"
class="com.cluster.customvalidate.PasswordIntegrityValidator"/>
</validators>
<validators>
<field name="password">
<field-validator type="passwordintegrity">
<message key="login.invalidFormat"></message>
</field-validator>
</field>
</validators>
Eg:-
public class UserNotFoundException extends RuntimeException{
}
2. Whenever u get the errors in Action class throw the exception and also add the ActionError
message.
For eg:
<global-results>
<result name="red">/jsp/noPhones.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception =
"com.cluster.exception.UserNotFoundException" result="red"/>
</global-exception-mappings>
4. Write the ActionError message in the property file for the given key.
5. Add the <s:actionerror/> tag in the jsp to display the error management
<body bgcolor="wheat">
<h2><s:actionerror/></h2>
</body>
Struts 2 Tiles
index.jsp
<html>
<body bgcolor="yellow">
<table border="2">
<tr height="10%">
<td><jsp:include page="header.jsp" /></td>
</tr>
<tr height="80%">
<td>
<table border="2">
<tr>
<td><jsp:include page="menu.jsp" /></td>
<td><jsp:include page="home.jsp" /></td>
</tr>
</table>
</td>
</tr>
<tr height="10%">
<td><jsp:include page="footer.jsp" /></td>
</tr>
</table>
</body>
</html>
• When we are developing a web based application we can write many jsps inside that and in every
jsp we can have some design layout.
• Sometimes we can have different design layouts for different jsps.
• We can develop this kind of layout using <jsp:include> but the problem is:-
1. Hard coding the jsp names inside the jsp. Because of hardcoding when we change one jsp name
we need to modify all the jsps in the application, which gives maintenance problem.
2. We will be duplicating the layout code in all the jsps. This gives code duplication problem.
• To solve the above problems apache has provided a special framework called tiles framework.
<web-app >
<context-param>
<param-name>tilesDefinition</param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class> org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener
</listener-class>
</listener>
</web-app>
<tr>
<td width="20%" bgcolor="green">
<tiles:insertAttribute name="lmenu"/>
</td>
<tr>
<td height="10%" bgcolor="yellow" colspan="3">
<tiles:insertAttribute name="footer"/>
</td>
</tr>
</table>
</body>
</html>
3. Develop the other content jsps (header.jsp, footer.jsp, menu.jsp, etc)
<html>
<body>
<tiles:insertDefinition name="HomeDef"/>
</body>
</html>
Interceptors
• Struts 2 uses interceptors to separate and reuse commonly required tasks or crosscutting concerns
for all action classes.
• Some interceptors only do work before the action has been executed, and others only do work after
request processing.
• Interceptors don't necessarily have to do something both times they fire but they do have the
opportunity.
• There is a stack of interceptors in front of the action.
• The invocation of the action must travel through this stack.
• The built-in interceptors handle most of the fundamental tasks ranging from data transfer,
validation, exception handling, etc.
• We generally always extend the defaultStack and by extending this we inherit many features of the
struts framework.
• While the defaultStack provides a common set of interceptors, arranged in a common sequence, to
serve the common functional needs of most requests, we can easily re-arrange them to meet
varying requirements. We can even remove and add particular interceptors as we like. We can even
do this on a per action basis, but this is seldom necessary.
• Most of the interceptors that we use are found in the struts-default package which is in the struts-
default.xml file.
• Following are few of the list of built-in interceptors which are configured in struts-default package of
struts-default.xml
1. alias 16. params
2. autowiring 17. prepare
3. chain 18. staticParams
4. conversionError 19. scope
5. cookie 20. servletConfig
6. createSession 21. sessionAutowiring
7. debugging 22. timer
8. externalRef 23. token
9. execAndWait 24. tokenSession
10. exception 25. validation
11. fileUpload 26. workflow
12. i18n 27. store
13. logger 28. checkbox
14. modelDriven 29. profiling
15. scopedModelDriven 30. roles
• There are many stacks defined in the struts-default packages of which two are important.
1. basicStack
2. defaultStack
• Struts also provides the facility to implement your own interceptors according to your application
requirement.
Step 4: Register the interceptor implemented by you in the <package> tag using the tag
<interceptors> and use the interceptor for your action class as follows :-
<interceptor-stack name="myStack">
<!-- <interceptor-ref name="defaultStack"/> -- > 1 option
<action name="ShowLogin">
<result>/jsp/login.jsp</result>
</action>
Note: The <default-interceptor-ref name="myStack" /> tag is used for reusing the stack.
Studying the built-in interceptors.
1. params :- interceptor collects the incoming parameters and transfers into properties of the action
class and then stores the action class in the ValueStack.
2. conversionError:- interceptor is used for converting the HTTP string values into the corresponding
java primitive or wrapper classes type. If any HTTP string value cannot be converted to a java type
then default error message will be reported which can be customized to display our own message.
3. workflow :- interceptor checks for basic validations. This interceptor does two things. First it checks
if the action is implementing Validateable interface. If it implements then the workflow interceptor
will invoke the validate() method for basic validations. Second if the validation fails then an error
message is created and added. Then the workflow interceptor will check if there are any error
messages. If the error exists, the workflow interceptor will stop execution, returns a control string
with the a value “input” and displays the input jsp.
4. validation:- interceptor is used for using validation framework. If we are using the validation
framework then validation interceptor will be fired and adds the error messages if any validation
fails. Then the workflow interceptor will check if there are any error messages. If the error exists, the
workflow interceptor will stop execution, returns a control string with the a value “input” and
displays the input jsp. To use this interceptor your action must implement ValidationAware
interface.
5. exception:- This important interceptor is responsible for doing exception handling in the application.
The exception interceptor comes first in the defaultStack, and should probably come first in any
custom stacks you might create yourself. The exception interceptor will catch exceptions and map
them, by type, to user defined error pages. It's position at the top of the stack guarantees that it will
be able to catch all exceptions that may be generated during all phases of the action invocation.
6. prepare:- interceptor looks for prepare() method and executes the method if your action class implements
Preparable interface. We generally override prepare() method if we want to write any pre-processing or
initializing code.
7. modelDriven:- This interceptor checks whether the action class is implementing ModelDriven or not.
If implementing then getmodel() will be called.
8. token and tokenSession:- The token and token-session interceptors can be used to prevent duplicate
form submissions. Duplicate form posts can occur when users click the Back button to go back to a
previously submitted form and then click the button again, or when they click the button more than
once while waiting for a response. The token interceptors work by passing a token in with the
request which is checked by the interceptor. If the unique token comes to the interceptor a second
time, the request is considered as a duplicate. These two interceptors both do the same thing,
differing only in the richness of their handling of the duplicate request. You can either show an error
page or save the original result to be re-rendered for the user.
To use the token interceptor your form should contain <s:token> tag .
9. servletConfig:- This interceptor checks whether the action class is implementing the different Aware
interfaces. It the action class is implementing the Aware interfaces then this interceptor will do dependency
injection of all the objects into the action class in the pre-processing phase.
10. i18n:- This interceptor sets the locale for the current request and helps to support doing
internationalization.
15. timer:- This interceptor logs the time taken for an execution. If you place this interceptor at the
heart of your stack, just before the action, then it will time the action's execution itself. If you place
it at the outer most layer of the stack, it will be timing the execution of the entire stack, as well as
the action.
16. execAndWait:- While running a long action users may get impatient in case of long delayed
response. To avoid this execAndWait interceptor is used. This runs the long running action in the
background and displays the page with progress block to the user. It also prevents the HttpRequest
time outs. To use this we have to specify two parameters
1. delay
2. delayInterval
17. alias:- In case of action chaining if you want to copy the one action variables data into another
action with different name we have to use this interceptor. When you are using this interceptor you
must explicitly configure this under the required action with following parameters
<action>
<param name="aliases">
#{‘username’ : ‘userId’ , ‘email’ : ’emailId’}
</param>
<interceptor-ref name="alias"/>
</action>
18. chain:- This interceptor is used to copy all objects in the value stack of currently executing Action
class to the value stack of next Action class to be executed in the action chaining.
Following is the way to configure the result to invoke another action.
<action>
<result name="success" type="chain">
doLogin
</result>
</action>