Introducing Struts 2 JaMU 07.02 – February 24, 2007 Thomas Wiradikusuma (thomas@wiradikusuma.com) Java User Group Indonesia
Struts 2 defined An elegant, extensible framework for building enterprise-ready Java web applications An MVC web framework Action-based Successor of the famous Struts framework (and WebWork 2, technically speaking)
Sweet spots Simple architecture Interceptors, Actions, Results from pluggable ObjectFactory Controller-based or page-based navigation Support for POJO, Annotation, JSF Cool, customizable tag library with OGNL support Value stack Spring as default inversion of control container QuickStart Built-in Ajax support Many convention-over-configuration and sensible defaults Easier to test (out of container) Brings the best of Struts 1 and WebWork 2, including their fanatic followers ;-)
Architecture Request arrives FilterDispatcher finds appropriate Action Interceptors get applied Method in Action executes (usually doing “core” stuff) Result renders output
Architecture, cont’d
ActionMapper Provide a mapping between HTTP requests and action invocation requests and vice-versa Default implementation uses standard *.[ext] (usually &quot;action&quot;) pattern. Extension is defined in Struts configuration key struts.action.exection. Prefixes: method:  <a:submit name=“method:bar” value=“Bar”/>   action:  <a:submit name=“action:foo” value=“Foo”/> redirect:  <a:submit name=“redirect:http://www.google.com” value=“Google”/> redirect-action:  <a:submit name=“redirect-action:foo” value=“Foo”/>
Interceptors <interceptor-stack name=&quot;xaStack&quot;> <interceptor-ref name=&quot;thisWillRunFirstInterceptor&quot;/> <interceptor-ref name=&quot;thisWillRunNextInterceptor&quot;/> <interceptor-ref name=&quot;followedByThisInterceptor&quot;/> <interceptor-ref name=&quot;thisWillRunLastInterceptor&quot;/> </interceptor-stack> thisWillRunFirstInterceptor thisWillRunNextInterceptor followedByThisInterceptor thisWillRunLastInterceptor MyAction1 MyAction2 (chain) MyPreResultListener MyResult (result) thisWillRunLastInterceptor followedByThisInterceptor thisWillRunNextInterceptor thisWillRunFirstInterceptor
Interceptors, cont’d Checks for valid token presence in Action, prevents duplicate form submission. token  Token And many more… Action will only be executed if the user has the correct JAAS role. roles  Roles If the Action implements Preparable, calls its prepare method.  prepare  Prepare Sets the request parameters onto the Action.  params  Parameters Executes the Action in the background and then sends the user off to an intermediate waiting page.  execAndWait  Execute and Wait Adds automatic checkbox handling code that detect an unchecked checkbox and add it as a parameter with a default (usually 'false') value. Uses a specially named hidden field to detect unsubmitted checkboxes.  checkbox  Checkbox Description Name Interceptor
Actions All actions may implement this interface, which exposes the execute() method. However, as of XWork 1.1, this is not required and is only here to assist users. You are free to create POJOs that honor the same contract defined by this interface without actually implementing the interface. ActionSupport class provides a default implementation for the most common actions.
Results Used for Velocity integration Velocity And many more… Used for Action Chaining Chain Used to stream an InputStream back to the browser (usually for file downloads) Stream Used to redirect to another action mapping Redirect Action Used to redirect to another URL (web resource)  Redirect Used for web resource integration, including JSP integration Dispatcher Usage Result
Type conversion Everything is String in HTTP Built-in: boolean, char, numeric types, dates, arrays, collections ClassName-conversion.properties: foo = package.FooConverter Globally in struts-conversion.properties in the root of your class path (typically WEB-INF/classes)  package.Foo = package.FooConverter Extend StrutsTypeConverter  to simplify creating a converter Throw TypeConversionException when conversion exception happens. Information will be displayed as specified in Struts configuration struts.default.invalid.fieldvalue
Localization Resource bundles are searched in the following order: ActionClass.properties  BaseClass.properties (all the way to Object.properties)  Interface.properties (every interface and sub-interface)  ModelDriven's model (if implements ModelDriven), for the model object repeat from 1  package.properties (of the directory where class is located and every parent directory all the way to the root directory)  search up the i18n message key hierarchy itself  global resource properties  Accessing key: getText: <s:property value=&quot;getText('some.key')&quot; />  text tag: <s:text name=&quot;some.key&quot; />  I18n tag to push an arbitrary resource bundle on to the value stack: <s:i18n name=&quot;some.package.bundle&quot; > <s:text name=&quot;some.key&quot; /> </s:i18n>
Configuration files Override the default Velocity configuration /WEB-INF/classes/  Yes velocity.properties Optional configuration files for plug-ins in the same format as struts.xml. Root of a plug-in JAR  Yes struts-plugin.xml  Default macros referenced by velocity.properties /WEB-INF/classes/  Yes struts-default.vm Default configuration provided by Struts /WEB-INF/lib/struts2-core.jar  Yes struts-default.xml Framework properties /WEB-INF/classes/  Yes struts.properties Main configuration, contains result/view types, action mappings, interceptors, and so forth /WEB-INF/classes/  Yes struts.xml Deployment descriptor /WEB-INF/  No web.xml Purpose  Location Optional? File
Taglib <% User user = ActionContext.getContext() %> <form action=&quot;Profile_update.action&quot; method=&quot;post&quot;> <table> <tr> <td> align=&quot;right&quot;><label>First name:</label></td> <td><input type=&quot;text&quot; name=&quot;user.firstname&quot; value=&quot;<%=user.getFirstname() %> /></td> </tr> <tr> <td> <input type=&quot;radio&quot; name=&quot;user.gender&quot; value=&quot;0&quot; id=&quot;user.gender0&quot;  <% if (user.getGender()==0) { %> checked=&quot;checked&quot; %> } %> /> <label for=&quot;user.gender0&quot;>Female</label> ... Without taglib (JSP): <s:actionerror/> <s:form action=&quot;Profile_update&quot; validate=&quot;true&quot;> <s:textfield label=&quot;Username&quot; name=&quot;username&quot;/> <s:password label=&quot;Password&quot; name=&quot;password&quot;/> <s:password label=&quot;(Repeat) Password&quot; name=&quot;password2&quot;/> <s:textfield label=&quot;Full Name&quot; name=&quot;fullName&quot;/> <s:textfield label=&quot;From Address&quot; name=&quot;fromAddress&quot;/> <s:textfield label=&quot;Reply To Address&quot; name=&quot;replyToAddress&quot;/> <s:submit value=&quot;Save&quot; name=&quot;Save&quot;/> <s:submit action=&quot;Register_cancel&quot; value=&quot;Cancel&quot; name=&quot;Cancel&quot; onclick=&quot;form.onsubmit=null&quot;/> </s:form> With taglib (JSP):
Taglib, cont’d <%@ taglib prefix=&quot;s&quot; uri=&quot;/struts-tags&quot; %>  Tags category: Control Data UI (form and non-form) Ajax
Servlet/JSP scoped object Application <s:property value=&quot;%{#application.foo}&quot; />   Session <s:property value=&quot;%{#session.foo}&quot; />   Request <s:property value=&quot;%{#request.foo}&quot; />   Parameter <s:property value=&quot;%{#parameter.foo}&quot; />   Context <s:property value=&quot;%{#foo}&quot; />
OGNL Object Graph Navigation Language More powerful than JSTL EL
Spring integration By default, the framework will at least try to use Spring to create all its objects. If the object cannot be created by Spring, then the framework will create the object itself.
Testing Direct Action invocation Out of container testing Testing Interceptors and/or Results
Struts 1 to Struts 2 Despite the similar name (Struts), migrating from Struts 1 is harder than migrating from WebWork 2. struts.xml struts-config.xml Action or POJO ActionForm Action or POJO Action (singleton) {action}-validation.xml validation.xml Result ActionForward Interceptors RequestProcessor FilterDispatcher ActionServlet Struts 2 Struts 1
WebWork 2 to Struts 2 Pretty much the same, only naming/namespace changes. <s:*/> <ww:*/> struts.xml xwork.xml struts.properties webwork.properties com.opensymphony.xwork2.* com.opensymphony.xwork.* “ struts” “ webwork” org.apache.struts2.* com.opensymphony.webwork.* Struts 2 WebWork 2
Requirements Servlet API 2.4 JSP API 2.0 Java 5 (or 1.4 with Retroweaver)
Integration with open source libraries Spring 2.0 Velocity Freemarker JasperReports DWR Apache Pluto dojo and many more…
Not discussed Annotation support JSF, Ajax support Plug-ins QuickStart Validation Value stack Wildcard mappings Zero configuration
Where to go from here Struts (1 and 2) http://struts.apache.org AppFuse 2 http://www.appfuse.org

Introducing Struts 2

  • 1.
    Introducing Struts 2JaMU 07.02 – February 24, 2007 Thomas Wiradikusuma (thomas@wiradikusuma.com) Java User Group Indonesia
  • 2.
    Struts 2 definedAn elegant, extensible framework for building enterprise-ready Java web applications An MVC web framework Action-based Successor of the famous Struts framework (and WebWork 2, technically speaking)
  • 3.
    Sweet spots Simplearchitecture Interceptors, Actions, Results from pluggable ObjectFactory Controller-based or page-based navigation Support for POJO, Annotation, JSF Cool, customizable tag library with OGNL support Value stack Spring as default inversion of control container QuickStart Built-in Ajax support Many convention-over-configuration and sensible defaults Easier to test (out of container) Brings the best of Struts 1 and WebWork 2, including their fanatic followers ;-)
  • 4.
    Architecture Request arrivesFilterDispatcher finds appropriate Action Interceptors get applied Method in Action executes (usually doing “core” stuff) Result renders output
  • 5.
  • 6.
    ActionMapper Provide amapping between HTTP requests and action invocation requests and vice-versa Default implementation uses standard *.[ext] (usually &quot;action&quot;) pattern. Extension is defined in Struts configuration key struts.action.exection. Prefixes: method: <a:submit name=“method:bar” value=“Bar”/> action: <a:submit name=“action:foo” value=“Foo”/> redirect: <a:submit name=“redirect:http://www.google.com” value=“Google”/> redirect-action: <a:submit name=“redirect-action:foo” value=“Foo”/>
  • 7.
    Interceptors <interceptor-stack name=&quot;xaStack&quot;><interceptor-ref name=&quot;thisWillRunFirstInterceptor&quot;/> <interceptor-ref name=&quot;thisWillRunNextInterceptor&quot;/> <interceptor-ref name=&quot;followedByThisInterceptor&quot;/> <interceptor-ref name=&quot;thisWillRunLastInterceptor&quot;/> </interceptor-stack> thisWillRunFirstInterceptor thisWillRunNextInterceptor followedByThisInterceptor thisWillRunLastInterceptor MyAction1 MyAction2 (chain) MyPreResultListener MyResult (result) thisWillRunLastInterceptor followedByThisInterceptor thisWillRunNextInterceptor thisWillRunFirstInterceptor
  • 8.
    Interceptors, cont’d Checksfor valid token presence in Action, prevents duplicate form submission. token Token And many more… Action will only be executed if the user has the correct JAAS role. roles Roles If the Action implements Preparable, calls its prepare method. prepare Prepare Sets the request parameters onto the Action. params Parameters Executes the Action in the background and then sends the user off to an intermediate waiting page. execAndWait Execute and Wait Adds automatic checkbox handling code that detect an unchecked checkbox and add it as a parameter with a default (usually 'false') value. Uses a specially named hidden field to detect unsubmitted checkboxes. checkbox Checkbox Description Name Interceptor
  • 9.
    Actions All actionsmay implement this interface, which exposes the execute() method. However, as of XWork 1.1, this is not required and is only here to assist users. You are free to create POJOs that honor the same contract defined by this interface without actually implementing the interface. ActionSupport class provides a default implementation for the most common actions.
  • 10.
    Results Used forVelocity integration Velocity And many more… Used for Action Chaining Chain Used to stream an InputStream back to the browser (usually for file downloads) Stream Used to redirect to another action mapping Redirect Action Used to redirect to another URL (web resource) Redirect Used for web resource integration, including JSP integration Dispatcher Usage Result
  • 11.
    Type conversion Everythingis String in HTTP Built-in: boolean, char, numeric types, dates, arrays, collections ClassName-conversion.properties: foo = package.FooConverter Globally in struts-conversion.properties in the root of your class path (typically WEB-INF/classes) package.Foo = package.FooConverter Extend StrutsTypeConverter to simplify creating a converter Throw TypeConversionException when conversion exception happens. Information will be displayed as specified in Struts configuration struts.default.invalid.fieldvalue
  • 12.
    Localization Resource bundlesare searched in the following order: ActionClass.properties BaseClass.properties (all the way to Object.properties) Interface.properties (every interface and sub-interface) ModelDriven's model (if implements ModelDriven), for the model object repeat from 1 package.properties (of the directory where class is located and every parent directory all the way to the root directory) search up the i18n message key hierarchy itself global resource properties Accessing key: getText: <s:property value=&quot;getText('some.key')&quot; /> text tag: <s:text name=&quot;some.key&quot; /> I18n tag to push an arbitrary resource bundle on to the value stack: <s:i18n name=&quot;some.package.bundle&quot; > <s:text name=&quot;some.key&quot; /> </s:i18n>
  • 13.
    Configuration files Overridethe default Velocity configuration /WEB-INF/classes/ Yes velocity.properties Optional configuration files for plug-ins in the same format as struts.xml. Root of a plug-in JAR Yes struts-plugin.xml Default macros referenced by velocity.properties /WEB-INF/classes/ Yes struts-default.vm Default configuration provided by Struts /WEB-INF/lib/struts2-core.jar Yes struts-default.xml Framework properties /WEB-INF/classes/ Yes struts.properties Main configuration, contains result/view types, action mappings, interceptors, and so forth /WEB-INF/classes/ Yes struts.xml Deployment descriptor /WEB-INF/ No web.xml Purpose Location Optional? File
  • 14.
    Taglib <% Useruser = ActionContext.getContext() %> <form action=&quot;Profile_update.action&quot; method=&quot;post&quot;> <table> <tr> <td> align=&quot;right&quot;><label>First name:</label></td> <td><input type=&quot;text&quot; name=&quot;user.firstname&quot; value=&quot;<%=user.getFirstname() %> /></td> </tr> <tr> <td> <input type=&quot;radio&quot; name=&quot;user.gender&quot; value=&quot;0&quot; id=&quot;user.gender0&quot; <% if (user.getGender()==0) { %> checked=&quot;checked&quot; %> } %> /> <label for=&quot;user.gender0&quot;>Female</label> ... Without taglib (JSP): <s:actionerror/> <s:form action=&quot;Profile_update&quot; validate=&quot;true&quot;> <s:textfield label=&quot;Username&quot; name=&quot;username&quot;/> <s:password label=&quot;Password&quot; name=&quot;password&quot;/> <s:password label=&quot;(Repeat) Password&quot; name=&quot;password2&quot;/> <s:textfield label=&quot;Full Name&quot; name=&quot;fullName&quot;/> <s:textfield label=&quot;From Address&quot; name=&quot;fromAddress&quot;/> <s:textfield label=&quot;Reply To Address&quot; name=&quot;replyToAddress&quot;/> <s:submit value=&quot;Save&quot; name=&quot;Save&quot;/> <s:submit action=&quot;Register_cancel&quot; value=&quot;Cancel&quot; name=&quot;Cancel&quot; onclick=&quot;form.onsubmit=null&quot;/> </s:form> With taglib (JSP):
  • 15.
    Taglib, cont’d <%@taglib prefix=&quot;s&quot; uri=&quot;/struts-tags&quot; %> Tags category: Control Data UI (form and non-form) Ajax
  • 16.
    Servlet/JSP scoped objectApplication <s:property value=&quot;%{#application.foo}&quot; /> Session <s:property value=&quot;%{#session.foo}&quot; /> Request <s:property value=&quot;%{#request.foo}&quot; /> Parameter <s:property value=&quot;%{#parameter.foo}&quot; /> Context <s:property value=&quot;%{#foo}&quot; />
  • 17.
    OGNL Object GraphNavigation Language More powerful than JSTL EL
  • 18.
    Spring integration Bydefault, the framework will at least try to use Spring to create all its objects. If the object cannot be created by Spring, then the framework will create the object itself.
  • 19.
    Testing Direct Actioninvocation Out of container testing Testing Interceptors and/or Results
  • 20.
    Struts 1 toStruts 2 Despite the similar name (Struts), migrating from Struts 1 is harder than migrating from WebWork 2. struts.xml struts-config.xml Action or POJO ActionForm Action or POJO Action (singleton) {action}-validation.xml validation.xml Result ActionForward Interceptors RequestProcessor FilterDispatcher ActionServlet Struts 2 Struts 1
  • 21.
    WebWork 2 toStruts 2 Pretty much the same, only naming/namespace changes. <s:*/> <ww:*/> struts.xml xwork.xml struts.properties webwork.properties com.opensymphony.xwork2.* com.opensymphony.xwork.* “ struts” “ webwork” org.apache.struts2.* com.opensymphony.webwork.* Struts 2 WebWork 2
  • 22.
    Requirements Servlet API2.4 JSP API 2.0 Java 5 (or 1.4 with Retroweaver)
  • 23.
    Integration with opensource libraries Spring 2.0 Velocity Freemarker JasperReports DWR Apache Pluto dojo and many more…
  • 24.
    Not discussed Annotationsupport JSF, Ajax support Plug-ins QuickStart Validation Value stack Wildcard mappings Zero configuration
  • 25.
    Where to gofrom here Struts (1 and 2) http://struts.apache.org AppFuse 2 http://www.appfuse.org