Wednesday, 13 April 2016

How to add Struts 2 framework in project ?


Add JARs to classpath
  • struts2-core-2.0.6.jar
  • xwork-2.0.1.jar
  • ognl-2.6.11.jar,
  • commons-fileupload-1.1.1.jar
  • commons-logging.jar
  • commons-logging-1.1.jar
  • freemarker-2.3.8.jar
  • jstl-1.1.0.jar
  • sitemesh-2.2.1.jar
  • struts2-sitemesh-plugin-2.0.6.jar


Configuration in web.xml

<!-- Struts2 Cleanup Filter config --><filter>
  <filter-name>struts-cleanup</filter-name>
  <filter-class> 
      org.apache.struts2.dispatcher.ActionContextCleanUp 
  </filter-class>
</filter>
<filter-mapping>
  <filter-name>struts-cleanup</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
 
<!-- Sitemesh configuration --><filter>
  <filter-name>sitemesh</filter-name>
  <filter-class> 
      com.opensymphony.module.sitemesh.filter.PageFilter 
  </filter-class>
</filter>
<filter-mapping>
  <filter-name>sitemesh</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
 
<!-- Struts2 Filter config --><filter>
  <filter-name>struts</filter-name>
  <filter-class> 
     org.apache.struts2.dispatcher.FilterDispatcher 
  </filter-class>
</filter>
<filter-mapping>
  <filter-name>struts</filter-name>
  <url-pattern>*.action</url-pattern>
</filter-mapping>


Adding Sitemesh configuration

1. Add sitemesh.xml, sitemesh-decorator.tld and sitemesh-page.tld in WEB-INF directory.
2. Add dwr.xml in WEB-INF directory.
3. Add decorators.xml in WEB-INF directory

<?xml version="1.0" encoding="ISO-8859-1"?>
<decorators defaultdir="/WEB-INF/decorators">
<!-- Any urls that are excluded will never be decorated by Sitemesh -->
<excludes>
<pattern>/index.jsp</pattern>
<pattern>/styles/*</pattern>
<pattern>/scripts/*</pattern>
<pattern>/images/*</pattern>
<pattern>/dojo/*</pattern>
<pattern>/struts/*</pattern>
</excludes>
<decorator name="main" page="main.jsp">
<pattern>/*</pattern>
</decorator>
</decorators>


Adding decorator JSP

Add main.jsp under WEB-INF/decorators directory
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%>
<%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="pages"%>
<html>
  <head>  
    <title> My Site - <decorator:title default="Welcome!" /></title> 
    <decorator:head />
  </head>
  <body>
   <table>
    <tr>
      <td bgcolor="skyblue">
        <pages applyDecorator page="/paneldata.html" 
               name="panel" title="Left Panel" />
      </td>
      <td> 
        <decorator:body />
      </td>
      <td bgcolor="gray">
        <pages:applyDecorator page="/paneldata.html" 
               name="panel" title="Right Panel" />
      </td>
     </tr>
    </table>
  </body> 
</html>

The decorator:body tag holds the actual page that is requested.
This is made possible by the filter mapping in web.xml and the mapping of "/*" to main layout in decorators.xml file.
Whereas in tiles, you have to push the pages into the template file, SiteMesh pulls the requested page into the template.


Adding struts.properties

Add struts.properties in any source folder directly (without any package)
### Struts default properties
###(can be overridden by a struts.properties file in the root of the classpath)
# struts.configuration = org.apache.struts2.config.DefaultConfiguration
### This can be used to set your default locale and encoding scheme
# struts.locale=en_US
struts.i18n.encoding=UTF-8
struts.objectFactory.spring.useClassCache = true
struts.multipart.parser=jakarta
struts.multipart.saveDir=
struts.multipart.maxSize=2097152
struts.action.extension=action
struts.serve.static=true
struts.serve.static.browserCache=true
struts.enable.DynamicMethodInvocation = true
struts.enable.SlashesInActionNames = false
struts.tag.altSyntax=true
struts.devMode = true
struts.i18n.reload=true
### Standard UI theme and dir where templates are stored
struts.ui.theme=qxhtml
struts.ui.templateDir=template
struts.ui.templateSuffix=ftl
struts.configuration.xml.reload=true
struts.url.http.port = 80
struts.url.https.port = 443
struts.url.includeParams = get
### Load custom default resource bundles
struts.custom.i18n.resources=com.shaan.resources.MessageResources
struts.dispatcher.parametersWorkaround = false
struts.freemarker.wrapper.altMap=true
struts.xslt.nocache=false
### A list of configuration files automatically loaded by Struts (in the given order)
struts.configuration.files=struts-default.xml,struts.xml,validators.xml
struts.mapper.alwaysSelectFullNamespace=false

You need to add struts-default.xml and struts.xml in same directory where struts.properties resides.
Also validation.xml need to be added under WEB-INF directory.


Adding struts-default.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="struts-default-custom">
  <result-types>
   <result-type name="chain" 
      class="com.opensymphony.xwork2.ActionChainResult"/>
   <result-type name="dispatcher" 
      class="org.apache.struts2.dispatcher.ServletDispatcherResult
      default="true"/>
   <result-type name="freemarker" 
      class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
   <result-type name="httpheader" 
      class="org.apache.struts2.dispatcher.HttpHeaderResult"/>   
   <result-type name="redirect" 
      class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
   <result-type name="redirect-action"                 
 class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
   <result-type name="stream" 
      class="org.apache.struts2.dispatcher.StreamResult"/>
   <result-type name="velocity" 
      class="org.apache.struts2.dispatcher.VelocityResult"/>
   <result-type name="xslt" 
      class="org.apache.struts2.views.xslt.XSLTResult"/>
   <result-type name="plaintext" 
      class="org.apache.struts2.dispatcher.PlainTextResult" />
 </result-types>

 <interceptors>
 <interceptor name="alias"
   class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>   
 <interceptor name="chain"
   class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
 <interceptor name="conversionError" 
 class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
 <interceptor name="createSession"
  class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
 <interceptor name="debugging"
 class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
 <interceptor name="external-ref"
 class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>  
 <interceptor name="execAndWait" 
  class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
 <interceptor name="exception" 
 class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
 <interceptor name="fileUpload"
  class="org.apache.struts2.interceptor.FileUploadInterceptor"/>  
 <interceptor name="i18n" 
  class="com.opensymphony.xwork2.interceptor.I18nInterceptor">
     <param name="attributeName">
         org.apache.struts.action.LOCALE
     </param>
 </interceptor>
 <interceptor name="logger"
  class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
 <interceptor name="model-driven"
 class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
 <interceptor name="scoped-model-driven"
 class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
 <interceptor name="params"
 class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
 <interceptor name="prepare"
 class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>   
 <interceptor name="static-params"
 class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
 <interceptor name="scope"
  class="org.apache.struts2.interceptor.ScopeInterceptor"/>
 <interceptor name="servlet-config"
  class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
 <interceptor name="timer"
  class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
 <interceptor name="token" 
  class="org.apache.struts2.interceptor.TokenInterceptor"/>
 <interceptor name="token-session"
 class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
 <interceptor name="validation" 
 class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
 <interceptor name="workflow" 
 class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
 <interceptor name="store"
  class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
 <interceptor name="checkbox"
  class="org.apache.struts2.interceptor.CheckboxInterceptor" />
 <interceptor name="profiling"
 class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
 <interceptor name="roles" 
  class="org.apache.struts2.interceptor.RolesInterceptor" />

 <!-- Basic stack -->
 <interceptor-stack name="basicStack">
     <interceptor-ref name="exception"/>
     <interceptor-ref name="servlet-config"/>
     <interceptor-ref name="prepare"/>
     <interceptor-ref name="checkbox"/>
     <interceptor-ref name="params"/>
     <interceptor-ref name="conversionError"/>
 </interceptor-stack>

 <!-- Sample validation and workflow stack -->
 <interceptor-stack name="validationWorkflowStack">
     <interceptor-ref name="basicStack"/>
     <interceptor-ref name="validation"/>
     <interceptor-ref name="workflow"/>
 </interceptor-stack>

 <!-- Sample file upload stack -->
 <interceptor-stack name="fileUploadStack">
     <interceptor-ref name="fileUpload"/>
     <interceptor-ref name="basicStack"/>
 </interceptor-stack>

 <!-- Sample model-driven stack -->
 <interceptor-stack name="modelDrivenStack">
     <interceptor-ref name="model-driven"/>
     <interceptor-ref name="basicStack"/>
 </interceptor-stack>

 <!-- Sample action chaining stack -->
 <interceptor-stack name="chainStack">
     <interceptor-ref name="chain"/>
     <interceptor-ref name="basicStack"/>
 </interceptor-stack>

 <!-- Sample i18n stack -->
 <interceptor-stack name="i18nStack">
     <interceptor-ref name="i18n"/>
     <interceptor-ref name="basicStack"/>
 </interceptor-stack>

 <!-- An example of the params-prepare-params trick. 
      This stack is exactly the same as the defaultStack, except 
      that it includes one extra interceptor before the prepare 
      interceptor: the params interceptor.
      This is useful for when you wish to apply parameters directly 
      to an object that you wish to load externally
      (such as a DAO or database or service layer), 
      but can't load that object until at least the ID parameter has been loaded. 
      By loading the parameters twice, you can retrieve the object 
      in the prepare() method, allowing the second params 
      interceptor to apply the values on the object. -->
 <interceptor-stack name="paramsPrepareParamsStack">
      <interceptor-ref name="exception"/>
      <interceptor-ref name="alias"/>
      <interceptor-ref name="params"/>
      <interceptor-ref name="servlet-config"/>
      <interceptor-ref name="prepare"/>
      <interceptor-ref name="i18n"/>
      <interceptor-ref name="chain"/>
      <interceptor-ref name="model-driven"/>
      <interceptor-ref name="fileUpload"/>
      <interceptor-ref name="checkbox"/>
      <interceptor-ref name="static-params"/>
      <interceptor-ref name="params"/>
      <interceptor-ref name="conversionError"/>
      <interceptor-ref name="validation">
        <param name="excludeMethods">input,back,cancel</param>
      </interceptor-ref>
      <interceptor-ref name="workflow">
        <param name="excludeMethods">input,back,cancel</param>
      <interceptor-ref>
 </interceptor-stack>

 <!-- A complete stack with all the common interceptors in place.
      Generally, this stack should be the one you use, 
      though it may do more than you need. 
      Also, the ordering can be switched around 
      Ex: if you wish to have your servlet-related objects applied 
          before prepare() is called, 
      you'd need to move servlet-config interceptor up.
      This stack also excludes from the normal validation and 
      workflow the method names input, back, and cancel. 
      These typically are associated with requests that should not 
      be validated. -->
 <interceptor-stack name="defaultStack">
      <interceptor-ref name="exception"/>
      <interceptor-ref name="alias"/>
      <interceptor-ref name="servlet-config"/>
      <interceptor-ref name="prepare"/>
      <interceptor-ref name="i18n"/>
      <interceptor-ref name="chain"/>
      <interceptor-ref name="debugging"/>
      <interceptor-ref name="profiling"/>
      <interceptor-ref name="scoped-model-driven"/>
      <interceptor-ref name="model-driven"/>
      <interceptor-ref name="fileUpload"/>
      <interceptor-ref name="checkbox"/>
      <interceptor-ref name="static-params"/>
      <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>

  <!-- The completeStack is here for backwards compatibility for 
      applications that still refer to the defaultStack by the old name -->
  <interceptor-stack name="completeStack">
       <interceptor-ref name="defaultStack"/>
  </interceptor-stack>

  <!-- Sample execute and wait stack.
       Note: execAndWait should always be the *last* interceptor -->
  <interceptor-stack name="executeAndWaitStack">
     <interceptor-ref name="execAndWait">
       <param name="excludeMethods">input,back,cancel</param>
     </interceptor-ref>
     <interceptor-ref name="defaultStack"/>
     <interceptor-ref name="execAndWait">
       <param name="excludeMethods">input,back,cancel</param>
     </interceptor-ref>
  </interceptor-stack> 

 </interceptors> 

 <default-interceptor-ref name="defaultStack"/> 

 <global-results> 
      <result name="securityError" type="redirect-action"> 
                  ../common/common_unAuthorisedAccess
      </result>
      <result name="sessionExpire" type="redirect-action"> 
                 ../common/common_sessionExpired
      </result> 
 </global-results>

</package>
</struts>


Adding 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>
  <constant name="struts.enable.DynamicMethodInvocation" value="true" />
  <constant name="struts.devMode" value="true" />

  <include file="/struts2config/Services.xml" />
  <package name="default" extends="struts-default">
       <default-interceptor-ref name="defaultStack" />
  </package>
</struts>

Here we added 3 files : struts.properties, struts-default.xml and struts.xml in any source folder directly (without any package).
In struts.xml, we included another XML, as you can make multiple struts configuration files module wise and include them in main struts.xml.


Struts configuration files

Make a file Services.xml under / struts2config folder, as specified in struts.xml.
Here, you can define your packages, namespaces, actions and results.
You can extend the package with the parent package defined in struts-default.xml, it will automatically include all features defined at its parent package : for example, struts-default-custom
<?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="login" namespace="/login" extends="struts-default-custom">
   <action name="Login_*" method="{1}" class="com.shaan.actions.LoginAction">
      <result name="input">/jsp/login/Login.jsp</result>
      <result name="result">/jsp/login/HomePage.jsp</result>
   </action>
   </package>
</struts>


Additionals

1. Add validation.xml and dwr.xml into /WEB-INF directory.
2. Add template folder under WebContent directory for themes.
3. Add template folder in any source folder directly for themes.

Note : if you do not want to use freemarker tags, you can avoid template directories and also delete its entries from struts.properties.
#struts.ui.theme=qxhtml
#struts.ui.templateDir=template
#struts.ui.templateSuffix=ftl


Actions

Create Action java classes to hold data as well as methods.
package com.shaan.actions;
public class LoginAction extends ActionSupport {
   String password;
   public String getPassword() {
      return password;
   }
   public void setPassword(String password) {
      this.password = password;
   }
   public String input() {
      return "input";
   }
   public String search() {
      System.out.println("Searching... password from action " 
                          + password);
      System.out.println("Searching... password from request " 
                          + _request.getParameter("password"));
  // business logic here
  return "result";
   }
}


JSP file

Make JSPs defined in struts configuration file under WebContent/jsp/login
Sample of login.jsp
<%@taglib prefix="s" uri="/struts-tags" %>
<s:form action="/login/Login_search.action" validate="true"   
        namespace="/login" name="loginForm">
    <s:textfield key="utils.password.label" name="password" size="20" />
    <s:submit key="login.btn.title">
</s:form>

Make sure, you have the resource bundles at the location as specified in struts.properties.
Like if you defined : 
struts.custom.i18n.resources=com.shaan.resources.MessageResources

You can have multiple locale specific resource bundles in Java package com.shaan.resources, like :
MessageResources.properties, MessageResources_en.properties, MessageResources_fr.properties etc.

For better understanding of configuration, go back to struts.properties and struts-default.xml.
Try to get meaning of all properties defined in these files.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.