You are currently reviewing an older revision of this page.

DRAFT INT-XXXX How to update legacy customizations

Purpose

The Struts library and its dependencies have been upgraded in Appian 18.1. This guide provides a set of instructions that users can follow to update existing legacy customizations.

The library version changes are:

  • Struts: 1.1 to 1.3.10-20.fc27 (provided by Fedora)
  • Taglibs: 1.0.6 to 1.2.3
  • Commons-chain: 1.1 to 1.2
  • Commons-beanutils: 1.8.0 to 1.9.3
  • Commons-digester: 1.5 to 1.8
  • Oro: 2.0.6 to 2.0.8

This legacy library upgrade affects customizations in the following types of files:

  • Struts configuration files (struts-config-*.xml)
  • Tag Library Descriptors (*.tld)
  • Java Server Pages (*.jsp)
  • Struts Actions (*.java).
  • web.xml

Instructions

  1. Core Struts JARs
  2. Web.xml Changes
  3. Add a Default Message Resource to Every Custom Struts Configuration File
  4. Use the Latest DTD Validators in Every Custom Struts Configuration File
    1. [Uncommon] XML Structure Changes
    2. Validating Your Struts Configuration Files
  5. JSP Replacements
    1. URI Replacements
    2. Replace Attributes of Form Tag
    3. Other Attribute Replacements

Core Struts JARs

If your customizations require copying Core Struts JARs to other folders (an uncommon scenario), please note that Struts now consists of multiple jars, including core, el, tiles, taglib, and extras.

Web.xml Changes

If you are using a custom web.xml file that overwrites the web.xml provided by Appian (an uncommon scenario), you will need to make the following changes.

  1. Find the Struts Action Servlet in the web.xml file. For example, look for:

    <servlet-name>action</servlet-name>
    <servlet-class>com.appiancorp.common.struts.AppianActionServlet</servlet-class>
  2. Make the same changes as found in the Appian-provided web.xml. Note: if you have a github branch that you merge with Appian to get Appian's changes, this step will happen when you merge the branches.
    1. Remove the debug parameter from the action servlet. It looks like this:
      <init-param>
      <param-name>debug</param-name>
      <param-value>2</param-value>
      </init-param>
    2. Remove the application parameter from the action servlet. It looks like this:
      <init-param>
      <param-name>application</param-name>
      <param-value>resources.application</param-value>
      </init-param>
    3. Add the following chainConfig parameter to the action servlet:
      <init-param>
      <param-name>chainConfig</param-name>
      <param-value>org/apache/struts/tiles/chain-config.xml</param-value>
      </init-param>
  3. [Uncommon] Address any additional customizations you have made to the Struts Action Servlet. The following <init-param> entries are no longer supported and should be removed:
    • mapping
    • bufferSize
      This is now supported by the <controller> element in the Framework Struts Configuration file.
    • content
      This is now supported by the <controller> element in the Framework Struts Configuration file, under the name contentType.
    • locale
      This is now supported by the <controller> element in the Framework Struts Configuration file.
    • maxFileSize
      This is now supported by the <controller> element in the Framework Struts Configuration file.
    • nocache
      This is now supported by the <controller> element in the Framework Struts Configuration file.
    • multipartClass
      This is now supported by the <controller> element in the Framework Struts Configuration file.
    • tempDir
      This is now supported by the <controller> element in the Framework Struts Configuration file.
    • factory
      This is now supported by the <message-resources> element in Struts Configuration files.
    • null
      This is now supported by the <message-resources> element in Struts Configuration files.

If you need to preserve the same functionality that these unsupported parameters were providing, they must be added to the appropriate Struts Configuration Files. For example,

You find this parameter inside your action servlet:
<init-param>
<param-name>maxFileSize</param-name>
<param-value>1G</param-value>
</init-param>

You would remove this parameter, and then add an equivalent set-property element the inside the <controller> element in your customized version of struts-config-framework.xml, like so:
<controller>
...
<set-property property="maxFileSize" value="1G" />
</controller>

Add a Default Message Resource to Every Custom Struts Configuration File

Due to the removal of the application init-param from the Struts Action Servlet as described in the previous section, a message-resources tag must be added to every Struts Configuration File.

  1. Search for all Struts Configuration Files. All Struts Configuration Files must start with struts-config-, so searching your customization directories for file names that match the form struts-config-*.xml should provide a list of files to update.
  2. Add message-resources tag. Add the following line to every Struts Configuration File that you have:

    <message-resources parameter="resources.application"/>

    This line must be added after the <action-mappings> tag, but before any <plug-in> tag and before the closing </struts-config> tag. Be sure to validate that your XML is still valid, as described in the next section.

Use the Latest DTD Validators in Every Custom Struts Configuration File

Document Type Definition (*.DTD) files are used to verify that Struts Configuration Files (struts-config-*.xml) are correct. Struts configuration files declare what DTD verification file to use at the top of the XML file. These declarations need to be updated to point to the latest DTD.

Example 1: change
<!DOCTYPE struts-config PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 1.1//EN' 'http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd'>
to
<!DOCTYPE struts-config PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 1.3//EN' 'http://struts.apache.org/dtds/struts-config_1_3.dtd'>

Note the change in two numbers as well as the path to the DTD.

Example 2: change
<!DOCTYPE struts-config PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 1.1//EN' '/struts-config_1_1.dtd' >
to
<!DOCTYPE struts-config PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 1.3//EN' '/struts-config_1_3.dtd' >

[Uncommon] XML Structure Changes

  • The debug parameter of the <controller> element is no longer supported and should be removed.
  • The dynamic parameter of the <form> element is no longer supported and should be removed.
  • The dynamic parameter of the <form-bean> element is no longer supported and should be removed.
  • The contextRelative parameter of the <forward> element is no longer supported and should be removed.
  • The <data-sources> and <data-source> elements are no longer supported and should be removed.

Validating Your Struts Configuration Files

After updating the XML file to point to the new DTD, open the XML file in a editor that verifies the XML against its DTD (e.g. IntelliJ IDEA, Eclipse, Visual Studio) and confirm that there are no errors.

Example Error: If you fail to construct the XML appropriately, you may get an app server error like this:
ERROR org.apache.commons.digester.Digester - Parse Error at line X column Y: The content of element type "struts-config" must match "(display-name?,description?,form-beans?,global-exceptions?,global-forwards?,action-mappings?,controller?,message-resources*,plug-in*)".

JSP Replacements

URI Replacements

Search all JSP files in your customization directories and check for the following:

Example 1: replace
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
with
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
in every JSP where it is found.

Example 2: replace
<%@ taglib uri="/WEB-INF/fmt.tld" prefix="fmt" %>
with
<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>
in every JSP where it is found.

Replace Attributes of Form Tag

Search all JSP files in your customization directories and check usages of the <form> tag. The name, scope, and type attributes are no longer supported and should be removed.

If you find these attributes, check the struts-config-*.xml file containing the action configuration corresponding to this JSP file. If the corresponding action already has these parameters defined with the same values, no further action is necessary. Otherwise, add these parameters to the action mapping.

Example:
You find this form in one of your JSPs:
<form name="dashboardForm" type="com.appiancorp.record.admin.UpdateDashboard" action="/admin/data/updateDashboard.do" scope="request">

You find the corresponding Struts Configuration file that contains the action mapping for the referenced action:
<action path="/admin/data/updateDashboard" type="com.appiancorp.record.admin.UpdateDashboard" name="dashboardForm" scope="request">
...
</action>

You confirm that the name, type, and scope parameters match the values specified on the form. Then, you remove those parameters from the form.

Other Attribute Replacements

  • Replace the name attribute of the bean:include tag with page
  • Replace the locale attribute of the html tag with lang
  • Replace the contextRelative attribute of the img tag with module

Cancellable Actions

Struts actions which are cancellable now need to be specified as such in their corresponding Struts Configuration File.

Where necessary, add the property and value cancellable="true" to the action:
<action path="..."
type="..."
name="..."
scope="..." >
cancellable="true">

Attempting to cancel an action which is not cancellable will result in an InvalidCancelException.

Unfortunately, we haven't found a good way to statically determine if an action is cancellable. It is recommended that you manually verify that performing (and cancelling if possible) every custom action in the GUI does not result in errors. However, if a less intensive approach is needed, setting cancellable="true" on every custom action may be acceptable.

Java API Changes

Search all Java and JSP files in your customization directories for the following replacements:

  • Action.perform
    • Replace usages with Action.execute
  • ActionError (namespace: org.apache.struts.action)
    • Replace usages with ActionMessage (namespace: org.apache.struts.action)
  • ValidatorUtil (namespace org.apache.commons.validator)
    Replace usages with ValidatorUtils (namespace org.apache.commons.validator.util)
  • org.apache.commons.validator.EmailValidator
    Replace usages with org.apache.commons.validator.routines.EmailValidator
  • The org.apache.struts.taglib.tiles namespace
    Replace usages with org.apache.struts.tiles.taglib
  • DataSourceConfig
    Remove usages
  • Action.defaultLocale
    Replace usages with Locale.getDefault
  • Action.getDataSource
    Remove usages
  • Action.LOCALE_KEY
    Replace usages with Globals.LOCALE_KEY
  • Action.saveErrors called with ActionErrors parameter
    Call with ActionMessages parameter instead
  • E.g. saveErrors(... actionErrors ...) becomes saveErrors(... actionMessages...)
    ActionErrors.GLOBAL_ERROR
  • Replace usages with ActionMessage.GLOBAL_MESSAGE
    ActionErrors.add called with ActionError parameter
  • Call with ActionMessage parameter instead
    E.g. add(... actionError …) becomes add(... actionMessage …)
  • ActionForward constructor called with contextRelative parameter
    Call without contextRelative parameter
  • E.g. ActionForward(... contextRelative …) becomes ActionForward(...)
    DynaActionFormClass.clear
  • Remove usages
    ExceptionHandler.storeException called with ActionError parameter
  • Call with ActionMessage parameter instead
    E.g. storeException(... actionError …) becomes storeException(... actionMessage …)
    RequestProcessor.log
    Remove or use Commons Logging class instead
    FormBeanConfig.setDynamic
    Remove usages
    ForwardConfig.contextRelative
    Replace usages with module
    ForwardConfig constructor called with contextRelative parameter
    Call with module parameter instead
    E.g. ForwardConfig(... contextRelative …) becomes ForwardConfig(... module ...)
    ModuleException.error
    Replace usages with message
    ModuleException.getError
    Replace usages with getActionMessage
    MultipartRequestWrapper.getRequest
    Now returns ServletRequestWrapper instead of HttpServletRequest
    Note: Casting to HttpServletRequest is safe
    validator.Resources.SERVLET_CONTEXT_KEY
    Replace usages with SERVLET_CONTEXT_PARAM
    validator.Resources.HTTP_SERVLET_REQUEST_KEY
    Replace usages with HTTP_SERVLET_REQUEST_PARAM
    validator.Resources.ACTION_ERRORS_KEY
    Replace usages with ACTION_MESSAGES_PARAM
    validator.Resources.getLocale
    Replace usages with RequestUtils.getUserLocale
    validator.Resources.getActionError
    Replace usages with getActionMessage
    RequestUtils.computeURL
    Replace usages with TagUtils.computeURL
    RequestUtils.selectModule
    Replace usages with ModuleUtils.selectModule
    RequestUtils.getModuleName
    Replace usages with ModuleUtils.getModuleName
    RequestUtils.getRequestModuleConfig
    Replace with ModuleUtils.getRequestModuleConfig
    RequestUtils.saveException
    Replace usages with TagUtils.saveException
    RequestUtils.getModuleConfig
    Replace usages with ModuleUtils.getModuleConfig
    RequestUtils.getModulePrefixes
    Replace usages with ModuleUtils.getModulePrefixes
    MessageTag.defaultLocale
    Remove usages
    BaseHandlerTag.defaultLocale
    Remove usages
    ErrorsTag.defaultLocale
    Remove usages
    JavascriptValidatorTag.defaultLocale
    Remove usages
    OptionTag.defaultLocale
    Remove usages
    ErrorsTag.lineEnd
    Remove usages
    HtmlTag.getCurrentLocale
    Remove usages
    ImgTag.isContextRelativeSet
    Remove usages
    ImgTag.lowsrc
    Remove usages
    TagUtils.getActionErrors
    Replace usages with getActionMessages
    TagUtils.getProperty
    Replace usages with PropertyUtils.getProperty
    ResponseUtils.write
    Replace usages with TagUtils.write
    ResponseUtils.writePrevious
    Replace usages with TagUtils.writePrevious
    RequestUtils and ResponseUtils usages not covered above
    Replace RequestUtils.* or ResponseUtils.* usages with TagUtils.getInstance().*