Struts 2 - Very good for learning/starting with Struts 2 version

Post on 18-Nov-2014

110 Views

Category:

Documents

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Very good for learning/starting with Struts 2 version

Transcript

Presentation on Struts 2Developed by Zackriya

Whats struts?

• Struts is a well-organized framework based on MVC architecture

• Apache Struts is an open-source framework that is used for developing Java web application

• Provided an excellent framework for developing application easily by organizing JSP and Servlet based on HTML formats and Java code.

Why struts 2.0• Programming the abstract classes instead of interfaces is one of design problem of struts1

framework that has been resolved in the struts 2 framework

• Simplified Actions - Actions are simple POJOs. Any java class with execute() method can be used as an Action class.

• No more ActionForms - ActionForms feature is no more known to the struts2 framework.

• Struts 2 Actions are HTTP independent

• Intelligent Defaults - Most configuration elements have a default value which can be set according to the need

• Better Tag features

• Annotations introduced : Applications in struts 2 can use Java 5 annotations as an alternative to XML and Java properties configuration.

Struts 1 vs 2• Servlet Dependency: Actions in Struts1 have dependencies on the servlet API since the

HttpServletRequest and HttpServletResponse objects are passed to the execute method when an Action is invoked but in case of Struts 2, Actions are not container dependent because they are made simple POJOs.

• Action classes: Programming the abstract classes instead of interfaces is one of design issues of struts1 framework that has been resolved in the struts 2 framework

• Threading Model: In Struts1, Action resources must be thread-safe or synchronized, there should only be one instance of a class to handle all requests for that Action. In Struts 2, Action objects are instantiated for each request, so there are no thread-safety issues.

• Harvesting inputs

• Expression Language: Struts1 integrates with JSTL. Struts 2 can also use JSTL, however it supports a more powerful and flexible expression language called "Object Graph Notation Language" (OGNL).

• Type Conversion

CONTROLLER- Filter Dispatcher• The role of the controller is played by the Struts 2

FilterDispatcher

• Is a servlet filter that inspects each incoming request to determine which Struts 2 action should handle the request

• The framework handles all of the controller work

• Just need to inform the framework which request URLs map to which of your actions.

• Two ways of informing the framework – XML and Java Annotation

Way to inform the frameworkXML:

<action name="Login" class="manning.Login"><result>/AccountPage.jsp</result><result name="input">/Login.jsp</result></action>

Java Annotation:

@Results({@Result(name="input", value="/Login.jsp" )@Result(value="/AccountPage.jsp" )})public class Login implements Action {public String execute() {//Business logic for login}}

Way to inform the framework.. contd

Model - Action• Struts 2 action serves two roles

• First, an action is an encapsulation of the calls to business logic into a single unit of work.

• Second, the action serves as a locus of data transfer.

• The controller hands over control of the request processing to the action by invoking it

• When the action completes its work, it’ll render a view back to the user who submitted the request, by forward the result to the Struts 2 view component

View - Result• The view is the presentation component of the

MVC pattern

• The role of the view is clear-cut: it translates the state of the application into a visual presentation with which the user can interact.

• Presentation can be represented by JSP or some other presentation layer technology

View - Result• The view is the presentation component of the

MVC pattern

• The role of the view is clear-cut: it translates the state of the application into a visual presentation with which the user can interact.

• Presentation can be represented by JSP or some other presentation layer technology

How Struts 2 works

Interceptors

• Interceptor allows common, cross-cutting tasks to be defined in clean, reusable components that you can keep separate from your action code.

• Interceptors are Struts 2 components that execute both before and after the action

• Logging is a typical cross-cutting scenario.

ValueStack and OGNL

• ValueStack is a storage area that holds all of the data associated with the processing of a request

• Rather than passing the data around, Struts 2 keeps it in a convenient, central location—the ValueStack

• OGNL is the tool that allows us to access the data we put in that central repository

• OGNL is an expression language that allows you to reference and manipulate the data on the ValueStack

Web.xml<?xml version="1.0" encoding="UTF-8"?><web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<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>

<welcome-file-list><welcome-file>index.html</welcome-file>

</welcome-file-list></web-app>

struts.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts><package name="default" namespace="/" extends="struts-default">

<action name="Menu"><result>/menu/Menu.jsp</result>

</action></package><include file="manning/demoWorld/demoWorld.xml"/></struts>

demoWorld.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC….><struts><package name="demoWorld" namespace="/demoWorld" extends="struts-default"><action name="Name"><result>/demoWorld/NameCollector.jsp</result></action>

<action name="HelloWorld" class="manning.demoWorld.HelloWorld"><result name="SUCCESS">/demoWorld/HelloWorld.jsp</result></action></package></struts>

Menu.jsp<%@ page contentType="text/html; charset=UTF-8" %><%@ taglib prefix="s" uri="/struts-tags" %><html>

<head> <title>Struts 2 in Action: Menu</title>

</head>

<body> <hr> <ul> <li><a href="<s:url action='demoWorld/Name'/>">HelloWorld</a></li> </ul> <hr>

</body>

</html>

struts.xml

NameCollector.jsp<%@ page contentType="text/html; charset=UTF-8" %><%@ taglib prefix="s" uri="/struts-tags" %><html>

<head> <title>Name Collector</title>

</head>

<body> <hr>

<h4>Enter your name so that we can customize a greeting just for you!</h4>

<s:form action="HelloWorld"> <s:textfield name="name" label="Your name"/> <s:submit/>

</s:form> <hr></body>

</html>

HelloWorld.jsp<%@ page contentType="text/html; charset=UTF-8" %><%@ taglib prefix="s" uri="/struts-tags" %><html>

<head> <title>HelloWorld</title>

</head>

<body>

<hr> <h3>Custom Greeting Page</h3>

<h4><s:property value="customGreeting"/></h4> <hr>

</body>

</html>

ValueStack as a repository

HelloWorld.java

D:\Tomcat 5.0\webapps\HelloWorld\WEB-INF

Directory structure

Action in detailAction encapsulates the unit of work through the execute() method

Action – Data Transfer• Request parameters from the form are moved to properties that

have matching names.

• In addition to receiving the incoming data from the request, these JavaBeans properties on the action will also expose the data to the result.

Action – result routingThe final duty of an action component is to return a control string that selects the result that should be rendered.

<action name="HelloWorld" class="manning.demoWorld.HelloWorld"><result name="SUCCESS">/demoWorld/HelloWorld.jsp</result><result name=“ERROR">/demoWorld/Error.jsp</result>

</action>

Packaging your actions

• name attribute is merely a logical name by which you can reference the package

<package name="demoWorld" namespace="/demoWorld" extends="struts-default">

<action name="Name"><result>/demoWorld/NameCollector.jsp</result>

</action>

Packaging your actions…contd• The namespace attribute is used to generate the URL namespace to which the actions of these packages are mapped.

• When a URL arrives as http://localhost:8080/HelloWorld/demoWorld/Name.action, the framework consults the /demoWorld namespace for the action named Name

<package name="demoWorld" namespace="/demoWorld" extends="struts-default"><action name="Name">

<result>/demoWorld/NameCollector.jsp</result></action>

Packaging your action (extends attribute)

• “extends” is similar to extends keyword in java

• “extends” attribute names another package whose components should be inherited by the current package.

<package name="demoWorld" namespace="/demoWorld" extends="struts-default">

<action name="Name"><result>/demoWorld/NameCollector.jsp</result>

</action>

Packaging your action (extends attribute)• The struts-default package, defined in the system’s struts-default.xml file, declares a huge set of commonly needed Struts 2 components ranging from complete interceptor stacks to all the common result types.

• Params interceptor has been the one moving data from request parameters to our action’s JavaBean properties

Validation through Action• Action to extend ActionSupport class to provide

validation

• workflow interceptor to be called after param interceptor

• workflow interceptor first looks for a validate() method on the action to invoke.

• If data doesn’t validate, create and store the error in addFieldError() method provided by ActionSupport class

• After execution of validate() method control goes back to the workflow interceptor

Validation through Action• workflow interceptor will check if any error

messages were generated

• If errors are found, then request processing is aborted and control returns back to the input form, where the appropriate error message will be displayed

• The control will go to a page where name attribute of result tag has “input” as the value

<result name="input">/demoWorld/NameCollector.jsp</result>

Validation code…

demoWorld.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE ….">

<struts><package name="demoWorld" namespace="/demoWorld" extends="struts-default">…..<action name="HelloWorld" class="manning.demoWorld.HelloWorld">

<result>/demoWorld/HelloWorld.jsp</result><result

name="input">/demoWorld/NameCollector.jsp</result></action></package></struts>

Validation code…

Validation_Demo

InterceptorsThe 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 that action executes

Interceptor invocation• First url mapping

• Create an object of the action and store it inside ActionInvocation object.

• Checks the extends property and sees the sequence of interceptor invocation in that xml

• References to that interceptors are add in the ActionInvocation

• ActionInvocation also stores references to the request object and map of the results available to the action.

Interceptor invocation… contdHow the interceptor fires• Framework calls the invoke() method of ActionInvocation,

ActionInvocation consults its state and executes whichever interceptor come next

• Invoke() method calls the Interceptors intercept() method which takes ActionInvocation as the parameter.

• intercept() calls the ActionInvocation.invoke() method inside, ActionInvocation consults its state and executes whichever interceptor comes next.

• Again invoke() method will call the intercept() method of the next Interceptors

• When all the interceptors() have been invoked, the invoke() method will cause the action itself to be executed.

Interceptor invocation… contd

• In normal execution, the invocation process tunnels down through all of the interceptors until, finally, there are no more interceptors in the stack and the action fires.

• ActionInvocation itself maintains the state of this process internal so it always knows where it is in the stack.

Interceptor invocation… contd

What does interceptor() do internally

1. Do some preprocessing2. Pass control on to successive interceptors, and ultimately the action, by calling invoke(), or divert execution by itself returning a control string.3. Do some postprocessing

Interceptor invocation… contd

intercept() method of the TimerInterceptor, one of the interceptors

public String intercept(ActionInvocation invocation) throws Exception {

long startTime = System.currentTimeMillis();

String result = invocation.invoke();long executionTime =

System.currentTimeMillis() - startTime;... log the time ...return result;

}

Interceptors - Timer

• This simple interceptor merely records the duration of 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 outermost layer of the stack, it’ll time the execution of the entire stack, as well as the action

Output:INFO: Executed action [/manning/demoWorld/HelloWorld] took 123

ms

Interceptors - Logger

• This interceptor provides a simple logging mechanism that logs an entry statement during preprocessing and an exit statement during postprocessing

Output: INFO: Starting execution stack for action

/manning/demoWorld/HelloWorldINFO: Finishing execution stack for action

/manning/demoWorld/HelloWorld

• This interceptor serves as a good demonstration of an interceptor that does processing both before and after the action executes.

Interceptors - Params • It transfers the request parameters to properties

exposed by the ValueStack

• To enable this transfer, the developer needs only to provide JavaBeans properties on her actions, using the same names as the form fields being submitted

• When Struts 2 receives a request, it immediately creates an ActionContext, a ValueStack, and an action object.

• As a carrier of application data, the action object is quickly placed on the ValueStack so that its properties will be accessible, via OGNL, to the far reaches of the framework(eg: incoming form prepopulation and for result rendering)

Interceptors – params… contd

•The params interceptor doesn’t know where the data is ultimately going; it just moves it to the first matching property it can find on the ValueStack

•There’s only one tricky bit about the ValueStack. The ValueStack pretends to be a single object when OGNL expressions are resolved against it

•If multiple occurrences of the same property exist, those lowest down in the stack are hidden by the uppermost occurrence of a similarly named property.

Interceptors – params… contd

• So how do the right objects get onto the ValueStack in time to receive the data transfer?

• Since the action is always put on the ValueStack at the start of a request-processing cycle, the action will be placed at the top and any request for a action property will be fetched since it will be at the top of the valuestack

Interceptors - STATIC-PARAMS

•This interceptor also moves parameters onto properties exposed on the ValueStack

•The difference is the origin of the parameters

•The parameters that this interceptor moves are defined in the action elements of the declarative architecture

eg:<action name="exampleAction"

class="example.ExampleAction"><param name="firstName">John</param><param name="lastName">Doe</param></action>

•These parameters are moved onto the ValueStack. In the defaultStack, the static-params interceptor fires before the params interceptor. This means that the request parameters will override values from the XML param element. You could, of course, change the order of these interceptors.

Interceptors - Workflow •It works with our actions to provide data validation and

subsequent workflow alteration if a validation error occurs.

public String intercept(ActionInvocation invocation)throws Exception {

Action action = invocation.getAction();if (action instanceof Validateable) {Validateable validateable = (Validateable) action;validateable.validate();}if (action instanceof ValidationAware) {ValidationAware validationAwareAction =ValidationAware) action;if (validationAwareAction.hasErrors()) {return Action.INPUT;}}return invocation.invoke();

}

Interceptors – workflow…contd•If the action has implemented the Validateable interface, the interceptor will invoke its validate() method to execute the action’s validation logic

•If the action implements the ValidationAware interface, the interceptor will check to see whether any errors were created by the validation logic by calling the hasErrors() method

•If some are present, the workflow interceptor takes the rather drastic step of completely halting execution of the action. It does this by returning its own INPUT control string

•Further execution stops immediately. The INPUT result is rendered, and postproc essing occurs as control climbs back out of the interceptor stack

Calling method apart from execute() as default-

Change in demoWorld.xml<action name="HelloWorld_*" method="{1}" class="manning.demoWorld.HelloWorld"><result>/demoWorld/HelloWorld.jsp</result><result name="input">/demoWorld/NameCollector.jsp</result>

</action>Change in NameCollector.jsp<s:form action="HelloWorld_edit"> <s:textfield name="name" label="Your name"/>

<s:submit/></s:form>

Interceptors - Exception • The exception interceptor comes first in the defaultStack, and should probably come first in any custom stacks you create yourself

<global-results><result name="error2">/menu/Menu.jsp</result><result name="error1">/index2.html</result>

</global-results><global-exception-mappings><exception-mapping exception="java.lang.NullPointerException" result="error1"/><exception-mapping exception="java.lang.Exception" result="error2"/>

User defined Interceptors

public class CapsInterceptor implements Interceptor {

public void destroy() { }public void init() { }

public String intercept( ActionInvocation actionInvocation ) throws Exception {

Action action = ( Action ) actionInvocation.getAction();if(action instanceof HelloWorld) { String name = ((HelloWorld)action).getName(); name = name.toUpperCase(); ((HelloWorld)action).setName(name); } System.out.println("CapsInterceptor in: interceptor"); return actionInvocation.invoke();}

}

User defined Interceptors…contd

Changes in demoWorld.xml

<interceptors><interceptor name="capsInterceptor"

class="manning.demoWorld.CapsInterceptor" />

<interceptor-stack name="myinterceptor"><interceptor-ref name="defaultStack" /><interceptor-ref name="capsInterceptor" />

</interceptor-stack>

</interceptors><default-interceptor-ref name="myinterceptor" />

OGNL

•OGNL stands for Object-Graph Navigation Lanugage.

•Its integrated with Struts 2 framework to help with data transfer and type conversion.

•Acts as a glue between the framework’s string-based HTTP input and output and the Java-based internal processing

•OGNL consists of two things: an expression language and type converters

OGNL – Expression Language

• Binds Java-side data properties to strings in the text-based view layers, commonly found in the name attributes of form input fields, or in various attributes of the Struts 2 tags.

Eg: <h5>Congratulations! You have created </h5><h3>The <s:property value=“phoneNumber" /> Portfolio</h3>

• This Struts 2 property tag takes a value from a property on one of our Java objects and writes it into the HTML in place of the tag

•The simplicity of the expression language makes for a ridiculously low learning curve

OGNL - Type Converters

OGNL - Type Converters

•Even in this simple case of the Struts 2 property tag in the view side, a conversion must be made from the Java type of the property referenced by the OGNL expression language to the string format of the HTML output.

•Struts 2 framework provides adequate built-in OGNL type converters

•OGNL first needs a context in which to search for its targets.

•Framework automatically transfers parameters to our action object, the action is sitting on something called the ValueStack

•User object is exposed as a JavaBeans property on our action object

OGNL - Type Converters .. contd•params interceptor will move the data from the request

object to the ValueStack

•params interceptor interprets the request parameter name as an OGNL expression to locate the correct destination property on the ValueStack

•Once the OGNL expression has been used to locate the destination property, the data can be moved onto that property by calling the property’s setter with the correct value.

OGNL - Type Converters … contd

•At this point, the original value in request is still the String “37” for age, here’s where the type converters come into play.

•For this OGNL will consult its set of available type converters to see if any of them can handle this particular conversion.

•Data out - procedure

Mapping of field names to propertiesvia OGNL

• <s:textfield name="user.username" label="Username"/>

Part of Action class User Class

private User user;

public User getUser() {

return user;

}

public void setUser(User user) {

this.user = user;

}

public class User {

private String username;

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}}

Mapping of field namesArrays Action class implementation

<s:form action="ArraysDataTransferTest">

<s:textfield name="ages" label="Ages"/>

<s:textfield name="ages" label="Ages"/>

<s:textfield name="ages" label="Ages"/>

<s:textfield name="names[0]" label="names"/>

<s:textfield name="names[1]" label="names"/>

<s:textfield name="names[2]" label="names"/>

<s:submit/>

</s:form>

private Double[] ages ;

public Double[] getAges() {

return ages;

}

public void setAges(Double[] ages) {

this.ages = ages;

}

private String[] names = new String[10];

public String[] getNames() {

return names;

}

public void setNames(String[] names) {

this.names = names;

}

Mapping of Array properties

• The ages property is an array of element type Double. OGNL sees this and automatically runs its type conversion for each element of the array.

• The ages property the framework will create an array for us, so we don’t need to initialize

• For names property we need to initialize the array with a size since the OGNL expressions are targeting individual elements of an existing array.

<h5>Congratulations! You have transferred and converted data to and from Arrays.</h5>

<h3>Age number 3 = <s:property value="ages[2]" /> </h3><h3>Name number 3 = <s:property value="names[2]" /> </h3>

Mapping of List properties

• You don’t have preinitialize any of your Lists, even the ones that’ll receive data from the indexed OGNL notation.

• Without any specification, the elements of these Lists will be of String objects.

<s:form action=“ListDataTransferTest"><s:textfield name="ages" label="Ages"/><s:textfield name="ages" label="Ages"/><s:textfield name="ages" label="Ages"/><s:textfield name="names[0]" label="names"/><s:textfield name="names[1]" label="names"/><s:textfield name="names[2]" label="names"/><s:submit/></s:form>

Mapping of List properties… contd

• If List need to handle non-string property, we need to define the non string mapping in a properties file.

• The file need to follow the below syntax

•If the Action file is ListDataTransferTest then the property file should be ListDataTransferTest-conversion.properties and place this file in the classpath

• If we want to tell OGNL that we want “Double” type of element in our List property, add the below line in the properties file

•Elements

Mapping of List properties… contd

<s:textfield name="weights[0]" label="weights"/><s:textfield name="weights[1]" label="weights"/><s:textfield name="weights[2]" label="weights"/>

• If we want to tell OGNL that weights property should be converted to “Double” type add the below line in the properties file

Element-weights=java.lang.Double

Control Tags

index.jsp

demoTag.xml

IfControlTag.jsp

index.jsp

IfControlTag.jsp

Demotag.xml

Append Tag

AppendTag.java AppendTag.jsp

The append tag is a generic tag that is used to merge multiple iterators into one iterator

AppendTag.java AppendTag.jsp

UI tag: textfield

Including a file: <s:include value="myBirthday.jsp" />

TextField tag:

<%@ taglib prefix="s" uri="/struts-tags" %> <h1><span style="background-color

: #FFFFcc">Textfield Tag Example!</span></h>  <s:form>    <s:textfield label="Employee Name" name="empname" size="15" maxlength="10" />  </s:form>  </body></html>

UI tag…contd

TextArea tag: <body>

  <h1><span style="background-color: #FFFFcc">Textarea Tag Example!</span></h>  <s:form>    <s:textarea label="Description" name="description" cols="15" rows="10" />  </s:form>  </body>

UI tag…contd

Radio tag: <body>

  <h1><span style="background-color: #FFFFcc">Radio Tag Example!</span></h>  <s:form>    <s:radio label="Fruits" name="fruitsname" list="fruits" />    <s:radio label="Animals" name="animalsname" list="animals" />  </s:form>  </body>

UI tag…contd

Checkbox tag: <body>

    <h1><span style="background-color: #FFFFcc">Checkbox Tag Example!</span></h1>      <b>Sex</b><br>      <s:checkbox label="Male" name="male" value="true" /><br>      <s:checkbox label="Female" name="male" />  </body>

UI tag…contd

TextArea tag: <body>

  <h1><span style="background-color: #FFFFcc">Textarea Tag Example!</span></h>  <s:form>    <s:textarea label="Description" name="description" cols="15" rows="10" />  </s:form>  </body>

UI tag…contd

TextArea tag: <body>

  <h1><span style="background-color: #FFFFcc">Textarea Tag Example!</span></h>  <s:form>    <s:textarea label="Description" name="description" cols="15" rows="10" />  </s:form>  </body>

UI tag…contd

TextArea tag: <body>

  <h1><span style="background-color: #FFFFcc">Textarea Tag Example!</span></h>  <s:form>    <s:textarea label="Description" name="description" cols="15" rows="10" />  </s:form>  </body>

top related