Installation

pom.xml

Add the following dependency to front-end pom.xml files

<dependency>
  <groupId>name.matthewgreet</groupId>
  <artifactId>struts-commons</artifactId>
  <version>1.7.2</version>
</dependency>

Local Maven Repository (Optional)

If not downloading from Maven Central Repository, install struts-commons-1.7.2.jar using the following.

mvn org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file -Dfile="struts-commons-1.7.2.jar"

struts.xml

Add the following constants to the application's struts.xml file.

<!-- Struts Commons properties, which have names prefixed by name.matthewgreet.strutscommons
     accept_classes - comma separated class names to automatically scan for bespoke policies, in addition to packages 
                      of accept_packages property, unless classpath scanning is disabled.  If both accept_classes and 
                      accept_packages are empty string, scans entire classpath, which is not recommended.  Defaults to 
                      empty string.  
     accept_packages - comma separated package names to scan for bespoke policies, in addition to classes of 
                       accept_classes property, unless classpath scanning is disabled.  If both accept_classes and 
                       accept_packages are empty string, scans entire classpath.  It's recommended to specify packages 
                       as entire classpath scanning takes a few seconds. Defaults to empty string.
     classpath_scanning_replace_built_in - if true, bespoke default converters found by automatic classpath scanning 
                                           replace built-in default converters.  Defaults to false.
     enable_classpath_scanning - if true, DefaultPolicyLookup automatically searches classpath for bespoke policies.  
                                 Defaults to false.  
     reject_classes - comma separated class names to be excluded from automatic classpath scanning. 
     reject_packages - comma separated package names to be excluded from automatic classpath scanning. 
     -->
<constant name="name.matthewgreet.strutscommons.accept_classes" value="" />
<constant name="name.matthewgreet.strutscommons.accept_packages" value="" />
<constant name="name.matthewgreet.strutscommons.classpath_scanning_replace_built_in" value="false" />
<constant name="name.matthewgreet.strutscommons.enable_classpath_scanning" value="false" />
<constant name="name.matthewgreet.strutscommons.reject_classes" value="" />
<constant name="name.matthewgreet.strutscommons.reject_packages" value="" />

Add the following interceptors to the application's struts.xml file.

<interceptor name="annotationValidation" class="name.matthewgreet.strutscommons.interceptor.AnnotationValidationInterceptor" />
<interceptor name="annotationValidation2" class="name.matthewgreet.strutscommons.interceptor.AnnotationValidationInterceptor2" />
<interceptor name="browserTab" class="name.matthewgreet.strutscommons.interceptor.BrowserTabInterceptor" />
<interceptor name="browserTab2" class="name.matthewgreet.strutscommons.interceptor.BrowserTabInterceptor2" />
<interceptor name="formFormatter" class="name.matthewgreet.strutscommons.interceptor.FormFormatterInterceptor" />
<interceptor name="formRetrieve" class="name.matthewgreet.strutscommons.interceptor.FormRetrieveInterceptor" />
<interceptor name="formStore" class="name.matthewgreet.strutscommons.interceptor.FormStoreInterceptor" />
<interceptor name="messageAmalgamation" class="name.matthewgreet.strutscommons.interceptor.MessageAmalgamationInterceptor" />
<interceptor name="messageRetrieve" class="name.matthewgreet.strutscommons.interceptor.MessageRetrieveInterceptor" >
<interceptor name="messageStore" class="name.matthewgreet.strutscommons.interceptor.MessageStoreInterceptor" />
<interceptor name="rejectedFormValues" class="name.matthewgreet.strutscommons.interceptor.RejectedFormValuesInterceptor" />
<interceptor name="unhandledException" class="name.matthewgreet.strutscommons.interceptor.UnhandledExceptionWriterInterceptor" />

Find the struts-default.xml file in the struts2-core-n.n.n.jar in use and create an interceptor stack by copying the defaultStack and deleting the interceptors shown.

<!-- This is the default stack minus the exception, params, conversionError, validation and workflow interceptors -->
<interceptor-stack name="CommonStackBottom">
  <interceptor-ref name="exception"/>
  <interceptor-ref name="alias"/>
  <interceptor-ref name="servletConfig"/>
  <interceptor-ref name="httpMethod"/>
  <interceptor-ref name="i18n"/>
  <interceptor-ref name="csp">
    <param name="disabled">false</param>
    <param name="enforcingMode">false</param>
  </interceptor-ref>
  <interceptor-ref name="prepare"/>
  <interceptor-ref name="chain"/>
  <interceptor-ref name="scopedModelDriven"/>
  <interceptor-ref name="modelDriven"/>
  <interceptor-ref name="fileUpload"/>
  <interceptor-ref name="actionFileUpload"/>
  <interceptor-ref name="checkbox"/>
  <interceptor-ref name="datetime"/>
  <interceptor-ref name="multiselect"/>
  <interceptor-ref name="staticParams"/>
  <interceptor-ref name="actionMappingParams"/>
  <interceptor-ref name="params"/>
  <interceptor-ref name="conversionError"/>
  <interceptor-ref name="coep">
    <param name="disabled">false</param>
    <param name="enforcingMode">false</param>
    <param name="exemptedPaths"/>
  </interceptor-ref>
  <interceptor-ref name="coop">
    <param name="disabled">false</param>
    <param name="exemptedPaths"/>
    <param name="mode">same-origin</param>
  </interceptor-ref>
  <interceptor-ref name="fetchMetadata">
    <param name="disabled">false</param>
  </interceptor-ref>
  <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-ref name="debugging"/>
</interceptor-stack>
  

Copy the following interceptor stacks.

<interceptor-stack name="CommonStackTop">
  <interceptor-ref name="browserTab2" />
</interceptor-stack>

 <interceptor-stack name="StandaloneStack">
   <interceptor-ref name="CommonStackTop" />
  <interceptor-ref name="annotationValidation2">
    <param name="excludeMethods">input,back,cancel,browse</param>
  </interceptor-ref>
  <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-ref name="CommonStackBottom" />
</interceptor-stack>

<!-- Stack for actions that find or update data but not display it -->
<interceptor-stack name="FormDrivenStack">
  <interceptor-ref name="CommonStackTop" />
  <interceptor-ref name="formStore" />
  <interceptor-ref name="messageStore" />
  <interceptor-ref name="unhandledException" />
  <interceptor-ref name="CommonStackBottom" />
  <interceptor-ref name="annotationValidation2">
    <param name="excludeMethods">input,back,cancel,browse</param>
  </interceptor-ref>
  <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>

<!-- Stack for actions that display data -->
<interceptor-stack name="ViewStack">
  <interceptor-ref name="CommonStackTop" />
  <interceptor-ref name="CommonStackBottom" />
  <interceptor-ref name="annotationValidation2">
    <param name="defaultMessageType">LOG_WARN</param>
    <param name="excludeMethods">input,back,cancel,browse</param>
    <param name="ignoreNonAnnotatedFields">true</param>
  </interceptor-ref>
  <interceptor-ref name="formRetrieve" />
  <interceptor-ref name="messageRetrieve" />
  <interceptor-ref name="messageAmalgamation" />
  <interceptor-ref name="formFormatter" />
  <interceptor-ref name="rejectedFormValues" />
</interceptor-stack>
  

JavaScript Libraries

Copy browserTab2.js into your app's JavaScript library.