struts2 - 101
TRANSCRIPT
Struts 2
1
Agenda
What is Struts ?
Features
How Struts works?
Request – Response Pipeline
Different components of Struts
Difference between Struts 1 and Struts 2
Creating your first Struts 2 Application
2
Background of Struts 2
Not Struts 1.x!
EE5 Web Framework
Originally OpenSymphony WebWork
WebWork + Struts + Apache
Incubator
Struts 2 was hatched in „07
3
What is Struts?
Feature of Struts
4
What exactly is Struts 2?
An MVC Framework
5
What exactly is Struts 2?
An MVC Framework
Is Open Source
Based on Java EE
Servlet API 2.4
JSP API 2.0
Java 5
6
Features
• Simple Architecture
7
Features
• Simple Architecture
• Spring as default inversion of control container
8
Features
• Simple Architecture
• Spring as default inversion of control container
• Page-based Navigation
9
Features
• Simple Architecture
• Spring as default inversion of control container
• Page-based Navigation
• Built-in Ajax Support: DWR and Dojo
10
Features
• Simple Architecture
• Spring as default inversion of control container
• Page-based Navigation
• Built-in Ajax Support: DWR and Dojo
• Much better client-side validation support
11
Features
• Simple Architecture
• Spring as default inversion of control container
• Page-based Navigation
• Built-in Ajax Support: DWR and Dojo
• Much better client-side validation support
• JSF Support
12
Features
• Simple Architecture
• Spring as default inversion of control container
• Page-based Navigation
• Built-in Ajax Support: DWR and Dojo
• Much better client-side validation support
• JSF Support
• Built-in support for testing with StrutsTestCase
13
How Struts works?
Request – Response Pipeline
14
Working of Struts 2 Framework
Core components of the framework
Interceptors
Actions
Results
Filter Dispatcher (Controller)
15
Request – Response Pipeline
16
Request – Response Pipeline – Step 1
17
Request – Response Pipeline – Step 2
18
Request – Response Pipeline – Step 3
19
Request – Response Pipeline – Step 4
20
Request – Response Pipeline – Step 5
21
Request – Response Pipeline – Step 6
22
Request – Response Pipeline – Step 7
23
Different Components of Struts
Core Component – Interceptor, Action & Result
Other concept – ValueStack, OGNL, Configuration Files, Validations
24
Interceptors
They provide a way to supply pre-processing and post-processing around
the action.
examples include double-submit guards, type conversion, object population,
validation, file upload, page preparation, exception handling
Not thread safe
<interceptors>
<interceptor name="autowiring“ class="interceptor.ActionAutowiringInterceptor"/>
</interceptors>
<action name="my" class="com.test.MyAction" >
<result>view.jsp</result>
<interceptor-ref name="autowiring"/>
</action>
25
Interceptor Stack
An interceptor has a specific role Parameter interception
Validation
Workflow
Named “stacks” provide pluggable lists pre-assembled for goal specific cases defaultStack
fileUploadStack
modelDrivenStack
paramsPrepareParamsStack
26
Common Interceptors Interceptor Description
Checkbox Interceptor Adds automatic checkbox handling code that detect an unchecked
checkbox and add it as a parameter with a default (usually 'false')
value.
Create Session
Interceptor
Create an HttpSession automatically, useful with certain
Interceptors that require a HttpSession to work properly (like the
TokenInterceptor)
File upload Interceptor An Interceptor that adds easy access to file upload support.
I18n Interceptor Remembers the locale selected for a user's session.
Logger Interceptor Outputs the name of the Action.
ExecuteAndWait
Interceptor
Executes the Action in the background and then sends the user off
to an intermediate waiting page. 27
Common Interceptors Cont’d Interceptor Description
Scope Interceptor Simple mechanism for storing Action state in the session or
application scope.
Parameters Interceptor Sets the request parameters onto the Action.
Roles Interceptor Action will only be executed if the user has the correct JAAS role.
Profiling Interceptor Activate profiling through parameter
Validation Interceptor Performs validation using the validators defined in action-
validation.xml
Exception Interceptor Maps exceptions to a result.
Cookie Interceptor Inject cookie with a certain configurable name / value into action.
28
Timer Interceptor
Stopwatch feature for action execution
“starts” before your action
“stops” afterward
Writes performance timings to log <interceptors>
<interceptor-stack name="stackWithTimer">
<interceptor-ref name="timer"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
records action's execution with interceptors
<interceptors>
<interceptor-stack name="stackWithTimer">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="timer"/>
</interceptor-stack>
</interceptors>
records only the action's execution time
29
Default Stack <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>
30
Actions
Extend ActionSupport
ThreadLocal (safe)
Contain your domain model or can be model driven
May contain multiple methods
Easy to test!
31
Action Mapping
<package name=“test" namespace="/test" extends="starter">
<action
name=“uri“ class=“class“ method=“method">
<result>destination</result>
</action>
<package>
32
Result
What should be returned to requester?
Many provided out of the box
It‟s easy to write your own
Graphics
JSON
It‟s another configurable object
33
Result Types
Result Type Description
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)
34
Result Types Cont’d
Result Type Description
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
PlainText Result Used to display the raw content of a particular page
(i.e jsp, HTML)
Tiles Result Used to provide Tiles integration
35
Result Example
<action …> <result name="success" type="dispatcher">
/employee/list.jsp
</result>
</action>
name and type are optional
name defaults to success
type default can be set by package
36
ValueStack & OGNL
A ValueStack is a place where all the data related to
action and the action itself is stored
OGNL is a mean through which the data in the
ValueStack is manipulated.
37
ValueStack • Leverages the OGNL framework
Object Graph Navigation Language
• Extends OGNL to support searching stack Top down to locate object/property
• Where Interceptors put/get object data
• Thread Safe
• ActionContext.getContext().getValueStack()
Map<String, Object> context = new HashMap<String, Object>();
context.put("key", "some object");
context.put("key2", "another object");
ActionContext.getContext().getValueStack().push(context);
38
Struts 2 and OGNL
39
ValueStack The Action instance is always pushed onto the value stack and since the stack is the
OGNL root, references to Action properties can omit the # marker. <s:property value=“customer.address"/>
But, to access other objects in the ActionContext, we must use the # notation so
OGNL knows not to look in the root object, but for some other object in the ActionContext. <s:property value="#session.mySessionPropKey"/> or <s:property value="#session['mySessionPropKey']"/> or <s:property value="#request['myRequestPropKey']"/>
The ActionContext is also exposed to Action classes via a static method. ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);
40
ValueStack The Action instance is always pushed onto the value stack and since the stack is the
OGNL root, references to Action properties can omit the # marker. <s:property value=“customer.address"/>
But, to access other objects in the ActionContext, we must use the # notation so
OGNL knows not to look in the root object, but for some other object in the ActionContext. <s:property value="#session.mySessionPropKey"/> or <s:property value="#session['mySessionPropKey']"/> or <s:property value="#request['myRequestPropKey']"/>
The ActionContext is also exposed to Action classes via a static method. ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);
41
ValueStack The Action instance is always pushed onto the value stack and since the stack is the
OGNL root, references to Action properties can omit the # marker. <s:property value=“customer.address"/>
But, to access other objects in the ActionContext, we must use the # notation so
OGNL knows not to look in the root object, but for some other object in the ActionContext. <s:property value="#session.mySessionPropKey"/> or <s:property value="#session['mySessionPropKey']"/> or <s:property value="#request['myRequestPropKey']"/>
The ActionContext is also exposed to Action classes via a static method. ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);
42
Type Conversions
43
OGNL uses reflection to convert types
JavaBeans convention provides “hint”
Custom converters can be added
Scope
Bean/Model
Action
Application
Configuration Files File Optional Location Purpose
Web.xml No /WEB_INF/ Web deployment descriptor to include
all necessary framework components
Struts.xml Yes /WEB_INF/classes Main configuration, contains result/view
types, action mappings, interceptors,
and so forth
Struts.prop
erties
Yes /WEB_INF/classes Framework properties
Strusts.defa
ult.xml
Yes /WEB-INF/lib/
struts2-core.jar
Default configuration provided by
Struts
44
struts.xml
Core configuration file for framework
Can contain multiple packages
45
<struts> <package name=“base“ extends="struts-default"> <result-types>…</result-types> <interceptors><interceptor-stack name="starterStack"> <interceptor-ref name="timer" /> <interceptor-ref name="scopedModelDriven" /> <interceptor-ref name="paramsPrepareParamsStack" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="starterStack" /> </package> <include file=“base.xml" /> <include file=“preferences.xml" /> </struts>
struts.properties
struts.devMode=true
struts.objectFactory=spring
struts.configuration.xml.reload=true
struts.freemarker.templatesCache=true
struts.ui.theme=simple
struts.enable.DynamicMethodInvocation=false
struts.custom.i18n.resources=resources.Messages
…
46
struts-default.xml Most of your packages will extend this
Directly/Indirectly
Contains about everything you need
Packages form inheritance hierarchies
The key sections are
package
result-types
interceptors/stacks
<package name=“base“ extends="struts-default"> <result-types>…</result-types> <interceptors><interceptor-stack name="starterStack"> <interceptor-ref name="timer" /> <interceptor-ref name="scopedModelDriven" /> <interceptor-ref name="paramsPrepareParamsStack" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="starterStack" /> </package>
47
Constant Configuration
48
Modify framework and plug-in behavior
Can be declared at multiple levels
Searched in the following order struts-default.xml
struts-plugin.xml
struts.xml
struts.properties
web.xml
Subsequent files override previous ones
Validations
Validation Styles
Annotations
XML
Java
Dependent on
Validation Interceptor
Workflow Interceptor
49
Simple Field Example
50
Form
<s:textfield key="age"/>
Action
private int age; get/set
Validator <ActionClassName>-validation.xml
<field name="age"> <field-validator type="int">
<param name="min">13</param>
<param name="max">19</param>
<message>must be between ${min} and ${max}, current value is ${bar}</message>
</field-validator>
</field>
Validator Types
51
conversion
date
short – int – long - double
regex <takes a regular expression>
required
requiredstring
stringlength
url
visitor - conditionalvisitor
fieldexpression <resolves an OGNL expression>
expression <resolves an OGNL expression>
Non-Field vs Field Validation
52
<validators>
<validator type="expression">
<param name="expression“> ( (a==b) && (b==c) )</param>
<message>all three fields must be the same></message>
</validator>
</validators>
<field name="email_address">
<field-validator type="required">
<message>You cannot leave the email address field empty.</message>
</field-validator>
<field-validator type="email">
<message>The email address you entered is not valid.</message> </field-
validator>
</field>
Difference between Struts 1 and
Struts 2
53
Action Classes
Struts 1 Struts 2
Struts 1 requires Action classes to
extend an abstract base class. A
common problem in Struts 1 is
programming to abstract classes
instead of interfaces.
An Struts 2 Action may implement
an Action interface, along with other
interfaces to enable optional and
custom services. Struts 2 provides a
base ActionSupport class to implement
commonly used interfaces. Albeit, the
Action interface is not required. Any
POJO object with a execute signature
can be used as an Struts 2 Action
object.
54
Threading Model
Struts 1 Struts 2
Struts 1 Actions are singletons and must be thread-safe since there will only be one instance of a class to handle all requests for that Action. The singleton strategy places restrictions on what can be done with Struts 1 Actions and requires extra care to develop. Action resources must be thread-safe or synchronized.
Struts 2 Action objects are instantiated
for each request, so there are no
thread-safety issues. (In practice,
servlet containers generate many
throw-away objects per request, and
one more object does not impose a
performance penalty or impact
garbage collection.)
55
Action Classes
Struts 1 Struts 2
Struts 1 requires Action classes to
extend an abstract base class. A
common problem in Struts 1 is
programming to abstract classes
instead of interfaces.
An Struts 2 Action may implement
an Action interface, along with other
interfaces to enable optional and
custom services. Struts 2 provides a
base ActionSupport class to implement
commonly used interfaces. Albeit, the
Action interface is not required. Any
POJO object with a execute signature
can be used as an Struts 2 Action
object.
56
Servlet Dependency
Struts 1 Struts 2
Struts 1 Actions have dependencies
on the servlet API since the
HttpServletRequest and
HttpServletResponse is passed to
the executemethod when an Action
is invoked.
Struts 2 Actions are not coupled to a
container. Most often the servlet
contexts are represented as simple
Maps, allowing Actions to be tested in
isolation. Struts 2 Actions can still access
the original request and response, if
required. However, other architectural
elements reduce or eliminate the need
to access the HttpServetRequest or
HttpServletResponse directly.
57
Testability
Struts 1 Struts 2
A major hurdle to testing Struts 1
Actions is that theexecute method
exposes the Servlet API. A third-
party extension, Struts TestCase,
offers a set of mock object for Struts
1.
Struts 2 Actions can be tested by
instantiating the Action, setting
properties, and invoking methods.
Dependency Injection support also
makes testing simpler.
58
Harvesting Input
Struts 1 Struts 2
Struts 1 uses an ActionForm object to capture input. Like Actions, all ActionForms must extend a base class. Since other JavaBeans cannot be used as ActionForms, developers often create redundant classes to capture input. DynaBeans can used as an alternative to creating conventional ActionForm classes, but, here too, developers may be redescribing existing JavaBeans.
Struts 2 uses Action properties as input
properties, eliminating the need for a second
input object. Input properties may be rich object
types which may have their own properties. The
Action properties can be accessed from the
web page via the taglibs. Struts 2 also supports
the ActionForm pattern, as well as POJO form
objects and POJO Actions. Rich object types,
including business or domain objects, can be
used as input/output objects. The ModelDriven
feature simplifies taglib references to POJO
input objects
59
Expression Language
Struts 1 Struts 2
Struts 1 integrates with JSTL, so it
uses the JSTL EL. The EL has basic
object graph traversal, but relatively
weak collection and indexed
property support.
Struts 2 can use JSTL, but the
framework also supports a more
powerful and flexible expression
language called "Object Graph
Notation Language" (OGNL).
60
Binding values into views
Struts 1 Struts 2
Struts 1 uses the standard JSP
mechanism for binding objects into
the page context for access.
Struts 2 uses a "ValueStack"
technology so that the taglibs can
access values without coupling your
view to the object type it is rendering.
The ValueStack strategy allows reuse
of views across a range of types which
may have the same property name but
different property types
61
Type Conversion
Struts 1 Struts 2
Struts 1 ActionForm properties are
usually all Strings. Struts 1 uses
Commons-Beanutils for type
conversion. Converters are per-class,
and not configurable per instance.
Struts 2 uses OGNL for type
conversion. The framework includes
converters for basic and common
object types and primitives
62
Validation
Struts 1 Struts 2
Struts 1 supports manual validation
via a validatemethod on the
ActionForm, or through an extension
to the Commons Validator. Classes
can have different validation contexts
for the same class, but cannot chain
to validations on sub-objects.
Struts 2 supports manual validation via
the validate method and the XWork
Validation framework. The Xwork
Validation Framework supports
chaining validation into sub-properties
using the validations defined for the
properties class type and the
validation context.
63
Control of method execution
Struts 1 Struts 2
Struts 1 supports separate Request
Processors (lifecycles) for each
module, but all the Actions in the
module must share the same
lifecycle.
Struts 2 supports creating different
lifecycles on a per Action basis via
Interceptor Stacks. Custom stacks can
be created and used with different
Actions, as needed.
64
Other Differences
Struts 1 Struts 2
Action Action
ActionForm Action or POJO
ActionForward Result
struts-config.xml struts.xml
ActionServlet FilterDispatcher
RequestProcessor Interceptors
validation.xml Action-validation.xml
65
Struts 2 Application
Creating your first Struts 2 App
66
Scenario(s)
2 use cases
View list of Employees
Add an Employee
Employee Attributes
• Name
• Age
• Date of Birth
• Gender
• Country
67
Pre-requisite
Need to have a following download and installed
Java EE 1.5
Java SDK 1.7
Tomcat 7.0
Struts 2 libraries
Database (like MySQL)
Development environment (Eclipse)
68
Scenario 1 – View list of employees
In the scenario, we will explore the following additional
components
Controller
Actions
Results
69
Scenario 1 – View list of employees – Step 1
Open Eclipse and create an dynamic
web application project
Add the struts jars to the class path
Configuring the controller in the
web.xml
70
Scenario 1 – View list of employees – Step 2a
Next, we will define
the Action class
71
Scenario 1 – View list of employees – Step 2b
Next, we will define
the Action
72
Scenario 1 – View list of employees – Step 3
Next, we will map the
Action to the result
in the struts.xml
73
Scenario 1 – View list of employees – Step 4
Next, we will see
the viewEmp.jsp
that was
configured as the
dispatcher jsp
74
Scenario 1 – View list of employees – Step 5
This completes all the steps in the scenario
We compile and deploy the war file in the tomcat
We hit the URL
http://localhost:8080/Struts2Application/view.action
75
Scenario 2 – Add an Employee
76
In the scenario, we will explore the following additional
components
Validations
Field
Non-Field
Interceptors
Scenario 2 – Add an Employee – Step 1
77
Define the JSP page
– addEmployee.jsp
with the struts 2
tags
Scenario 2 – Add an Employee – Step 2
78
Define the Action
class – AddEmployeeAction.java
Scenario 2 – Add an Employee – Step 2
79
Define the Action
class – AddEmployeeAction.java
Scenario 2 – Add an Employee – Step 3
80
Next, lets define validation for
the following fields as
Age
Mandatory Field
Value should be between 18
and 60
Date of birth
Mandatory Field
Date format should be DD-
MM-YYYY
Name
Mandatory field
Scenario 2 – Add an Employee – Step 3
81
Next, lets define validation for
the following fields as
Age
Mandatory Field
Value should be between 18
and 60
Date of birth
Mandatory Field
Date format should be DD-
MM-YYYY
Name
Mandatory field
Scenario 2 – Add an Employee – Step 3
82
Next, lets define validation for
the following fields as
Age
Mandatory Field
Value should be between 18
and 60
Date of birth
Mandatory Field
Date format should be DD-
MM-YYYY
Name
Mandatory field
Scenario 2 – Add an Employee – Step 3
83
Next, lets define validation for
the following fields as
Age
Mandatory Field
Value should be between 18
and 60
Date of birth
Mandatory Field
Date format should be DD-
MM-YYYY
Name
Mandatory field
Scenario 2 – Add an Employee – Step 3
84
Next, lets define validation for
the following fields as
Age
Mandatory Field
Value should be between 18
and 60
Date of birth
Mandatory Field
Date format should be DD-
MM-YYYY
Name
Mandatory field
Scenario 2 – Add an Employee – Step 4
85
Next , we will see
the changes in the
struts.xml
Scenario 2 – Add an Employee – Step 4
86
Next , we will see
the changes in the
struts.xml
Scenario 2 – Add an Employee – Step 5
87
Where is the
validator
interceptor
defined?
Scenario 2 – Add an Employee – Step 5
88
How do I
override the
default ?
Scenario 2 – Add an Employee – Step 5
89
How do I
override the
default ?
Scenario 2 – Add an Employee – Step 5
90
How do I
override the
default ?
Scenario 2 – Add an Employee – Step 5
91
How do I
override the
default ?
Scenario 2 – Add an Employee – Step 6
92
Coming back to
the Action class
Scenario 2 – Add an Employee – Step 7
93
So overall, we added or changed the following files
Added
AddEmployeeAction.java
AddEmployeeAction-validation.xml
AddEmployeeAction.properties
addEmployee.jsp
Changed
Struts.xml
Scenario 2 – Add an Employee – Step 8
This completes all the steps in the scenario
We compile and deploy the war file in the tomcat
We hit the URL
http://localhost:8080/Struts2Application/addEmp.action
94
Scenario 2 – Add an Employee – Step 9
95
Press Enter
Scenario 2 – Add an Employee – Step 9
96
Press Enter
Conclusion
97
This concludes the programming demo
Refer to struts 2 documentation for more in-depth
details on each of the components
98