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
- Core Struts JARs
- web.xml Changes
- Add a Default Message Resource to Every Custom Struts Configuration File
- Use the Latest DTD Validators in Every Custom Struts Configuration File
- JSP Replacements
- Cancellable Actions
- Java API Changes
- 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:
-
Find the Struts Action Servlet in the
web.xmlfile. E.g., look for:<servlet-name>action</servlet-name><servlet-class>com.appiancorp.common.struts.AppianActionServlet</servlet-class> - Make the same changes as found in the Appian-provided
web.xml.- Remove the
debugparameter from theactionservlet. It looks like this:<init-param><param-name>debug</param-name><param-value>2</param-value></init-param> - Remove the
applicationparameter from theactionservlet. It looks like this:
<init-param><param-name>application</param-name><param-value>resources.application</param-value></init-param> - Add the following
chainConfigparameter to theactionservlet:
<init-param>
<param-name>chainConfig</param-name>
<param-value>org/apache/struts/tiles/chain-config.xml</param-value>
</init-param>
- Remove the
- [Uncommon] Address any additional customizations made to the Struts Action Servlet. The following
<init-param>entries are no longer supported and should be removed:
mappingbufferSize- This is now supported by the
<controller>element in the Framework Struts Configuration file.
- This is now supported by the
content- This is now supported by the
<controller>element in the Framework Struts Configuration file, under the name contentType.
- This is now supported by the
locale- This is now supported by the
<controller>element in the Framework Struts Configuration file.
- This is now supported by the
maxFileSize- This is now supported by the
<controller>element in the Framework Struts Configuration file.
- This is now supported by the
nocache- This is now supported by the
<controller>element in the Framework Struts Configuration file.
- This is now supported by the
multipartClass- This is now supported by the
<controller>element in the Framework Struts Configuration file.
- This is now supported by the
tempDir- This is now supported by the
<controller>element in the Framework Struts Configuration file.
- This is now supported by the
factory- This is now supported by the
<message-resources>element in Struts Configuration files.
- This is now supported by the
null- This is now supported by the
<message-resources>element in Struts Configuration files.
- This is now supported by the
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.
- 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 formstruts-config-*.xmlshould provide a list of files to update. -
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
debugparameter of the<controller>element is no longer supported and should be removed. - The
dynamicparameter of the<form>element is no longer supported and should be removed. - The
dynamicparameter of the<form-bean>element is no longer supported and should be removed. - The
contextRelativeparameter 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
nameattribute of thebean:includetag withpage - Replace the
localeattribute of thehtmltag withlang - Replace the
contextRelativeattribute of theimgtag withmodule
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
- Replace usages with
ActionError(namespace:org.apache.struts.action)- Replace usages with
ActionMessage(namespace:org.apache.struts.action)
- Replace usages with
ValidatorUtil(namespace:org.apache.commons.validator)- Replace usages with
ValidatorUtils(namespace:org.apache.commons.validator.util)
- Replace usages with
org.apache.commons.validator.EmailValidator- Replace usages with
org.apache.commons.validator.routines.EmailValidator
- Replace usages with
- The
org.apache.struts.taglib.tilesnamespace- Replace usages with
org.apache.struts.tiles.taglib
- Replace usages with
DataSourceConfig- Remove usages
Action.defaultLocale- Replace usages with
Locale.getDefault
- Replace usages with
Action.getDataSource- Remove usages
Action.LOCALE_KEY- Replace usages with
Globals.LOCALE_KEY
- Replace usages with
Action.saveErrorscalled withActionErrorsparameter- Call with
ActionMessagesparameter instead - E.g.
saveErrors(... actionErrors ...)becomessaveErrors(... actionMessages...)
- Call with
ActionErrors.GLOBAL_ERROR- Replace usages with
ActionMessage.GLOBAL_MESSAGE
- Replace usages with
ActionErrors.addcalled withActionErrorparameter- Call with
ActionMessageparameter instead - E.g.
add(... actionError …)becomesadd(... actionMessage …)
- Call with
ActionForwardconstructor called withcontextRelativeparameter- Call without contextRelative parameter
- E.g.
ActionForward(... contextRelative …)becomesActionForward(...)
DynaActionFormClass.clear- Remove usages
ExceptionHandler.storeExceptioncalled withActionErrorparameter- Call with
ActionMessageparameter instead - E.g.
storeException(... actionError …)becomesstoreException(... actionMessage …)
- Call with
RequestProcessor.log- Remove, or use Commons Logging class instead
FormBeanConfig.setDynamic- Remove usages
ForwardConfig.contextRelative- Replace usages with
module
- Replace usages with
ForwardConfigconstructor called withcontextRelativeparameter- Call with
moduleparameter instead - E.g.
ForwardConfig(... contextRelative …)becomesForwardConfig(... module ...)
- Call with
ModuleException.error- Replace usages with
message
- Replace usages with
ModuleException.getError- Replace usages with
getActionMessage
- Replace usages with
MultipartRequestWrapper.getRequest- Now returns
ServletRequestWrapperinstead ofHttpServletRequest - Note: Casting to
HttpServletRequestis safe
- Now returns
validator.Resources.SERVLET_CONTEXT_KEY- Replace usages with
SERVLET_CONTEXT_PARAM
- Replace usages with
validator.Resources.HTTP_SERVLET_REQUEST_KEY- Replace usages with
HTTP_SERVLET_REQUEST_PARAM
- Replace usages with
validator.Resources.ACTION_ERRORS_KEY- Replace usages with
ACTION_MESSAGES_PARAM
- Replace usages with
validator.Resources.getLocale- Replace usages with
RequestUtils.getUserLocale
- Replace usages with
validator.Resources.getActionError- Replace usages with
getActionMessage
- Replace usages with
RequestUtils.computeURL- Replace usages with
TagUtils.computeURL
- Replace usages with
RequestUtils.selectModule- Replace usages with
ModuleUtils.selectModule
- Replace usages with
RequestUtils.getModuleName- Replace usages with
ModuleUtils.getModuleName
- Replace usages with
RequestUtils.getRequestModuleConfig- Replace with
ModuleUtils.getRequestModuleConfig
- Replace with
RequestUtils.saveException- Replace usages with
TagUtils.saveException
- Replace usages with
RequestUtils.getModuleConfig- Replace usages with
ModuleUtils.getModuleConfig
- Replace usages with
RequestUtils.getModulePrefixes- Replace usages with
ModuleUtils.getModulePrefixes
- Replace usages with
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
- Replace usages with
- TagUtils.getProperty
- Replace usages with
PropertyUtils.getProperty
- Replace usages with
ResponseUtils.write- Replace usages with
TagUtils.write
- Replace usages with
ResponseUtils.writePrevious- Replace usages with
TagUtils.writePrevious
- Replace usages with
RequestUtilsandResponseUtilsusages not covered above- Replace
RequestUtils.*orResponseUtils.*usages withTagUtils.getInstance().*
- Replace
Notes
- Any URIs seen in this document are internal to the Appian product. E.g. Usages of
jakarta.apache.orgorstruts.apache.orgdo 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
