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:
This legacy library upgrade affects customizations in the following types of files:
struts-config-*.xml
*.tld
*.jsp
*.java
web.xml
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.
core
el
tiles
taglib
extras
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.xml file. E.g., look for:
<servlet-name>action</servlet-name><servlet-class>com.appiancorp.common.struts.AppianActionServlet</servlet-class>
<servlet-name>action</servlet-name>
<servlet-class>com.appiancorp.common.struts.AppianActionServlet</servlet-class>
debug
action
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
application
<param-name>application</param-name>
<param-value>resources.application</param-value>
chainConfig
<init-param> <param-name>chainConfig</param-name> <param-value>org/apache/struts/tiles/chain-config.xml</param-value></init-param>
mapping
bufferSize
<controller>
content
locale
maxFileSize
nocache
multipartClass
tempDir
factory
<message-resources>
null
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>
<param-name>maxFileSize</param-name>
<param-value>1G</param-value>
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>
set-property
struts-config-framework.xml
...
<set-property property="maxFileSize" value="1G" />
</controller>
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.
init-param
message-resources
struts-config-
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.
<action-mappings>
<plug-in>
</struts-config>
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.
*.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'>
<!DOCTYPE struts-config PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 1.1//EN' 'http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd'>
<!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' >
<!DOCTYPE struts-config PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 1.1//EN' '/struts-config_1_1.dtd' >
<!DOCTYPE struts-config PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 1.3//EN' '/struts-config_1_3.dtd' >
dynamic
<form>
<form-bean>
contextRelative
<forward>
<data-sources>
<data-source>
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*)".
Search all JSP files in the customization directories and check for the following:
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.
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
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.
<%@ taglib uri="/WEB-INF/fmt.tld" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>
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.
name
scope
type
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">
<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>
<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.
form
bean:include
page
html
lang
img
module
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">
cancellable="true"
<action path="..."
type="..."
name="..."
scope="..." >
cancellable="true">
Attempting to cancel an action which is not cancellable will result in an InvalidCancelException.
cancellable
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.
Search all Java and JSP files in the customization directories for the following replacements:
Action.perform
Action.execute
ActionError
org.apache.struts.action
ActionMessage
ValidatorUtil
org.apache.commons.validator
ValidatorUtils
org.apache.commons.validator.util
org.apache.commons.validator.EmailValidator
org.apache.commons.validator.routines.EmailValidator
org.apache.struts.taglib.tiles
org.apache.struts.tiles.taglib
DataSourceConfig
Action.defaultLocale
Locale.getDefault
Action.getDataSource
Action.LOCALE_KEY
Globals.LOCALE_KEY
Action.saveErrors
ActionErrors
ActionMessages
saveErrors(... actionErrors ...)
saveErrors(... actionMessages...)
ActionErrors.GLOBAL_ERROR
ActionMessage.GLOBAL_MESSAGE
ActionErrors.add
add(... actionError …)
add(... actionMessage …)
ActionForward
ActionForward(... contextRelative …)
ActionForward(...)
DynaActionFormClass.clear
ExceptionHandler.storeException
storeException(... actionError …)
storeException(... actionMessage …)
RequestProcessor.log
FormBeanConfig.setDynamic
ForwardConfig.contextRelative
ForwardConfig
ForwardConfig(... contextRelative …)
ForwardConfig(... module ...)
ModuleException.error
message
ModuleException.getError
getActionMessage
MultipartRequestWrapper.getRequest
ServletRequestWrapper
HttpServletRequest
validator.Resources.SERVLET_CONTEXT_KEY
SERVLET_CONTEXT_PARAM
validator.Resources.HTTP_SERVLET_REQUEST_KEY
HTTP_SERVLET_REQUEST_PARAM
validator.Resources.ACTION_ERRORS_KEY
ACTION_MESSAGES_PARAM
validator.Resources.getLocale
RequestUtils.getUserLocale
validator.Resources.getActionError
RequestUtils.computeURL
TagUtils.computeURL
RequestUtils.selectModule
ModuleUtils.selectModule
RequestUtils.getModuleName
ModuleUtils.getModuleName
RequestUtils.getRequestModuleConfig
ModuleUtils.getRequestModuleConfig
RequestUtils.saveException
TagUtils.saveException
RequestUtils.getModuleConfig
ModuleUtils.getModuleConfig
RequestUtils.getModulePrefixes
ModuleUtils.getModulePrefixes
MessageTag.defaultLocale
BaseHandlerTag.defaultLocale
ErrorsTag.defaultLocale
JavascriptValidatorTag.defaultLocale
OptionTag.defaultLocale
ErrorsTag.lineEnd
HtmlTag.getCurrentLocale
ImgTag.isContextRelativeSet
ImgTag.lowsrc
TagUtils.getActionErrors
getActionMessages
PropertyUtils.getProperty
ResponseUtils.write
TagUtils.write
ResponseUtils.writePrevious
TagUtils.writePrevious
RequestUtils
ResponseUtils
RequestUtils.*
ResponseUtils.*
TagUtils.getInstance().*
jakarta.apache.org
struts.apache.org
This article applies to Appian 18.1 and later.
Last Reviewed: January 2018