KB-1506 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
  5. JSP Replacements
  6. Cancellable Actions
  7. Java API Changes
  8. Notes

Core Struts JARs

If your customizations require copying Core Struts JARs to specific folders (an uncommon scenario), please note that Struts now consists of multiple jars, including core, el, tiles, taglib, and extras. Be sure to download Struts from Fedora (see link above) and copy all the jars if needed. Otherwise, the Appian installation will provide the jars by default and no action is needed.

web.xml Changes

If using a custom web.xml file that overwrites the web.xml provided by Appian (an uncommon scenario), make the following changes:

  1. Find the Struts Action Servlet in the web.xml file. E.g., 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
    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 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 the 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 available:

    <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 the 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 of the correct structure. Struts configuration files declare which DTD verification file to use at the top of the XML file. This declaration needs to be updated to point to the latest DTD in every Struts Configuration File.

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 the 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. If the XML is not constructed appropriately, the following error may be thrown:

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 the customization directories and check for the following:

Replace With
http://jakarta.apache.org/struts/tags-bean http://struts.apache.org/tags-bean
http://jakarta.apache.org/struts/tags-nested http://struts.apache.org/tags-nested
http://jakarta.apache.org/struts/tags-html http://struts.apache.org/tags-html
http://jakarta.apache.org/struts/tags-logic http://struts.apache.org/tags-logic
http://jakarta.apache.org/struts/tags-tiles http://struts.apache.org/tags-tiles
/WEB-INF/c.tld http://java.sun.com/jstl/core
/WEB-INF/fmt.tld http://java.sun.com/jstl/fmt
/WEB-INF/sql.tld http://java.sun.com/jstl/sql
/WEB-INF/x.tld http://java.sun.com/jstl/xml
/WEB-INF/c-rt.tld http://java.sun.com/jstl/core_rt
/WEB-INF/fmt-rt.tld http://java.sun.com/jstl/fmt_rt
/WEB-INF/sql-rt.tld http://java.sun.com/jstl/sql_rt
/WEB-INF/x-rt.tld http://java.sun.com/jstl/xml_rt


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 the customization directories and check usages of the <form> tag. The name, scope, and type attributes are no longer supported and should be removed.

If these attributes are present, 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.

Since there isn't a good way to statistically determine if an action is cancellable, it is recommended to 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 the 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().*

Notes

  • Any URIs seen in this document are internal to the Appian product. E.g. Usages of jakarta.apache.org or struts.apache.org do not point to an external resource from the web.
  • The instructions in this document were put together by upgrading a common set of customizations and may not cover your particular situation. For additional information on how to upgrade struts customizations, see https://wiki.apache.org/struts/StrutsUpgrade, and contact Appian Technical Support for additional questions.

Affected Versions

This article applies to Appian 18.1 and later.

Last Reviewed: January 2018

Related
Recommended