You are currently reviewing an older revision of this page.

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

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. 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.xmlNote: 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. 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:

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 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().*

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.