struts2 - 101

98
Struts 2 1

Upload: munish-kumar-gupta

Post on 24-May-2015

1.712 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Struts2 - 101

Struts 2

1

Page 2: Struts2 - 101

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

Page 3: Struts2 - 101

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

Page 4: Struts2 - 101

What is Struts?

Feature of Struts

4

Page 5: Struts2 - 101

What exactly is Struts 2?

An MVC Framework

5

Page 6: Struts2 - 101

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

Page 7: Struts2 - 101

Features

• Simple Architecture

7

Page 8: Struts2 - 101

Features

• Simple Architecture

• Spring as default inversion of control container

8

Page 9: Struts2 - 101

Features

• Simple Architecture

• Spring as default inversion of control container

• Page-based Navigation

9

Page 10: Struts2 - 101

Features

• Simple Architecture

• Spring as default inversion of control container

• Page-based Navigation

• Built-in Ajax Support: DWR and Dojo

10

Page 11: Struts2 - 101

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

Page 12: Struts2 - 101

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

Page 13: Struts2 - 101

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

Page 14: Struts2 - 101

How Struts works?

Request – Response Pipeline

14

Page 15: Struts2 - 101

Working of Struts 2 Framework

Core components of the framework

Interceptors

Actions

Results

Filter Dispatcher (Controller)

15

Page 16: Struts2 - 101

Request – Response Pipeline

16

Page 17: Struts2 - 101

Request – Response Pipeline – Step 1

17

Page 18: Struts2 - 101

Request – Response Pipeline – Step 2

18

Page 19: Struts2 - 101

Request – Response Pipeline – Step 3

19

Page 20: Struts2 - 101

Request – Response Pipeline – Step 4

20

Page 21: Struts2 - 101

Request – Response Pipeline – Step 5

21

Page 22: Struts2 - 101

Request – Response Pipeline – Step 6

22

Page 23: Struts2 - 101

Request – Response Pipeline – Step 7

23

Page 24: Struts2 - 101

Different Components of Struts

Core Component – Interceptor, Action & Result

Other concept – ValueStack, OGNL, Configuration Files, Validations

24

Page 25: Struts2 - 101

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

Page 26: Struts2 - 101

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

Page 27: Struts2 - 101

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

Page 28: Struts2 - 101

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

Page 29: Struts2 - 101

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

Page 30: Struts2 - 101

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

Page 31: Struts2 - 101

Actions

Extend ActionSupport

ThreadLocal (safe)

Contain your domain model or can be model driven

May contain multiple methods

Easy to test!

31

Page 32: Struts2 - 101

Action Mapping

<package name=“test" namespace="/test" extends="starter">

<action

name=“uri“ class=“class“ method=“method">

<result>destination</result>

</action>

<package>

32

Page 33: Struts2 - 101

Result

What should be returned to requester?

Many provided out of the box

It‟s easy to write your own

Graphics

JSON

PDF

It‟s another configurable object

33

Page 34: Struts2 - 101

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

Page 35: Struts2 - 101

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

Page 36: Struts2 - 101

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

Page 37: Struts2 - 101

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

Page 38: Struts2 - 101

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

Page 39: Struts2 - 101

Struts 2 and OGNL

39

Page 40: Struts2 - 101

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

Page 41: Struts2 - 101

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

Page 42: Struts2 - 101

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

Page 43: Struts2 - 101

Type Conversions

43

OGNL uses reflection to convert types

JavaBeans convention provides “hint”

Custom converters can be added

Scope

Bean/Model

Action

Application

Page 44: Struts2 - 101

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

Page 45: Struts2 - 101

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>

Page 46: Struts2 - 101

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

Page 47: Struts2 - 101

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

Page 48: Struts2 - 101

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

Page 49: Struts2 - 101

Validations

Validation Styles

Annotations

XML

Java

Dependent on

Validation Interceptor

Workflow Interceptor

49

Page 50: Struts2 - 101

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>

Page 51: Struts2 - 101

Validator Types

51

conversion

date

email

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>

Page 52: Struts2 - 101

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>

Page 53: Struts2 - 101

Difference between Struts 1 and

Struts 2

53

Page 54: Struts2 - 101

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

Page 55: Struts2 - 101

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

Page 56: Struts2 - 101

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

Page 57: Struts2 - 101

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

Page 58: Struts2 - 101

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

Page 59: Struts2 - 101

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

Page 60: Struts2 - 101

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

Page 61: Struts2 - 101

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

Page 62: Struts2 - 101

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

Page 63: Struts2 - 101

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

Page 64: Struts2 - 101

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

Page 65: Struts2 - 101

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

Page 66: Struts2 - 101

Struts 2 Application

Creating your first Struts 2 App

66

Page 67: Struts2 - 101

Scenario(s)

2 use cases

View list of Employees

Add an Employee

Employee Attributes

• Name

• Age

• Date of Birth

• Gender

• Country

67

Page 68: Struts2 - 101

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

Page 69: Struts2 - 101

Scenario 1 – View list of employees

In the scenario, we will explore the following additional

components

Controller

Actions

Results

69

Page 70: Struts2 - 101

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

Page 71: Struts2 - 101

Scenario 1 – View list of employees – Step 2a

Next, we will define

the Action class

71

Page 72: Struts2 - 101

Scenario 1 – View list of employees – Step 2b

Next, we will define

the Action

72

Page 73: Struts2 - 101

Scenario 1 – View list of employees – Step 3

Next, we will map the

Action to the result

in the struts.xml

73

Page 74: Struts2 - 101

Scenario 1 – View list of employees – Step 4

Next, we will see

the viewEmp.jsp

that was

configured as the

dispatcher jsp

74

Page 75: Struts2 - 101

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

Page 76: Struts2 - 101

Scenario 2 – Add an Employee

76

In the scenario, we will explore the following additional

components

Validations

Field

Non-Field

Interceptors

Page 77: Struts2 - 101

Scenario 2 – Add an Employee – Step 1

77

Define the JSP page

– addEmployee.jsp

with the struts 2

tags

Page 78: Struts2 - 101

Scenario 2 – Add an Employee – Step 2

78

Define the Action

class – AddEmployeeAction.java

Page 79: Struts2 - 101

Scenario 2 – Add an Employee – Step 2

79

Define the Action

class – AddEmployeeAction.java

Page 80: Struts2 - 101

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

Page 81: Struts2 - 101

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

Page 82: Struts2 - 101

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

Page 83: Struts2 - 101

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

Page 84: Struts2 - 101

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

Page 85: Struts2 - 101

Scenario 2 – Add an Employee – Step 4

85

Next , we will see

the changes in the

struts.xml

Page 86: Struts2 - 101

Scenario 2 – Add an Employee – Step 4

86

Next , we will see

the changes in the

struts.xml

Page 87: Struts2 - 101

Scenario 2 – Add an Employee – Step 5

87

Where is the

validator

interceptor

defined?

Page 88: Struts2 - 101

Scenario 2 – Add an Employee – Step 5

88

How do I

override the

default ?

Page 89: Struts2 - 101

Scenario 2 – Add an Employee – Step 5

89

How do I

override the

default ?

Page 90: Struts2 - 101

Scenario 2 – Add an Employee – Step 5

90

How do I

override the

default ?

Page 91: Struts2 - 101

Scenario 2 – Add an Employee – Step 5

91

How do I

override the

default ?

Page 92: Struts2 - 101

Scenario 2 – Add an Employee – Step 6

92

Coming back to

the Action class

Page 93: Struts2 - 101

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

Page 94: Struts2 - 101

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

Page 95: Struts2 - 101

Scenario 2 – Add an Employee – Step 9

95

Press Enter

Page 96: Struts2 - 101

Scenario 2 – Add an Employee – Step 9

96

Press Enter

Page 97: Struts2 - 101

Conclusion

97

This concludes the programming demo

Refer to struts 2 documentation for more in-depth

details on each of the components

Page 98: Struts2 - 101

98