Currently I am using Struts 2.3.12 in my project and all the things are working fine. Now I have requirement to upgrade Struts version to 2.3.20 to address some security issue.
I changed the Struts and required Struts plugins version to 2.3.20 in my project pom.xml
and build the project war. Now, I am trying to access my application home URL then getting following exception:
There is no Action mapped for namespace
[/web/public]
and action name[reset-password!reset]
associated with context path[/ims]
. - [unknown location]
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37)
com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:554)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
org.josso.tc55.agent.SSOAgentValve.invoke(SSOAgentValve.java:472)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
java.lang.Thread.run(Thread.java:662)
I couldn't get a single clue on what is happening.
I looked into the release note of struts 2.3.20 but I am not getting any hint.
I'm using strust2-convention-plugin
.
I am sharing my web.xml
and struts.xml
files. It looks like as following:
web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="jail" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>ims</display-name>
<!-- JCaptcha servlet mapping -->
<servlet>
<servlet-name>jcaptcha</servlet-name>
<servlet-class>com.sapienza.jail.controller.jcaptcha.JailImageCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jcaptcha</servlet-name>
<url-pattern>/web/public/jcaptcha.jpg</url-pattern>
</servlet-mapping>
<!-- Filters -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>ResponseOverrideFilter</filter-name>
<filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ResponseOverrideFilter</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/web/public/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<!-- JSP configuration -->
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
<page-encoding>UTF-8</page-encoding>
<include-prelude>/jsp/common/taglibs.jspf</include-prelude>
</jsp-property-group>
</jsp-config>
<welcome-file-list>
<welcome-file>/jsp/common/home.jsp</welcome-file>
</welcome-file-list>
<!-- Spring Listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Skin listener -->
<listener>
<listener-class>com.sapienza.jail.listener.ResourceListener</listener-class>
</listener>
<!-- LDAP Synchronisation Listeneer -->
<listener>
<listener-class>com.sapienza.jail.listener.LdapSyncListener</listener-class>
</listener>
<!-- Tiles listener -->
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
<context-param>
<param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
<param-value>/WEB-INF/tiles/skins-definitions.xml,/WEB-INF/tiles/pages-definitions.xml</param-value>
</context-param>
<context-param>
<param-name>org.apache.tiles.evaluator.AttributeEvaluator</param-name>
<param-value>org.apache.tiles.evaluator.el.ELAttributeEvaluator</param-value>
</context-param>
</web-app>
struts.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml"/>
<constant name="struts.objectFactory" value="spring"/>
<constant name="struts.devMode" value="true"/>
<constant name="struts.convention.default.parent.package" value="base-configuration"/>
<constant name="struts.convention.classes.reload" value="true"/>
<constant name="struts.enableJSONValidation" value="true"/>
<!-- struts configuration common for the whole application -->
<include file="struts-base.xml"/>
</struts>
struts-base.xml
:
<struts>
<!-- This package is abstract. It is not mean to declare any actions, only
common components such as interceptors, global results ... -->
<package name="base-configuration" abstract="true" extends="tiles-default">
<result-types>
<result-type name="jasper" class="org.apache.struts2.views.jasperreports.JasperReportsResult"/>
<result-type name="json" class="org.apache.struts2.json.JSONResult"/>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
</result-types>
<!-- create a custom paramsPrepareParamsStack using our log4j interceptor -->
<interceptors>
<!-- declaration of the custom interceptor using log4j to log exceptions. -->
<interceptor name="log4jExceptionMappingInterceptor" class="log4jExceptionMappingInterceptor" />
<!-- declaration of the custom security interceptor -->
<interceptor name="securityInterceptor" class="securityInterceptor" />
<!-- declaration of the custom SearchBean interceptor -->
<interceptor name="searchBeanInterceptor" class="searchBeanInterceptor" />
<!-- declaration of the custom WhiteSpaceTrim interceptor -->
<interceptor name="whiteSpaceTrimmerInterceptor" class="whiteSpaceTrimmerInterceptor" />
<!-- Struts2 JSON Validation -->
<interceptor name="jsonValidation" class="org.apache.struts2.json.JSONValidationInterceptor" />
<interceptor-stack name="imsDefaultStack">
<!-- insert log4j interceptor inserted in the custom stack -->
<interceptor-ref name="log4jExceptionMappingInterceptor" />
<!-- insert the custom security interceptor -->
<interceptor-ref name="securityInterceptor" />
<interceptor-ref name="alias" />
<interceptor-ref name="params" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params" />
<!-- excludes base CRUD methods from the validation process -->
<!-- validation interceptor triggers the xml validation -->
<interceptor-ref name="validation">
<param name="validateAnnotatedMethodOnly">true</param>
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
<!-- ajax validation interceptor -->
<interceptor-ref name="jsonValidation">
<param name="excludeMethods">input</param>
</interceptor-ref>
<!-- workflow interceptor triggers programmatic validation (calls validate()) -->
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
</interceptor-stack>
<!-- this new custom stack will be used for public URL -->
<interceptor-stack name="imsNoSecurityStack">
<!-- insert log4j interceptor inserted in the custom stack -->
<interceptor-ref name="log4jExceptionMappingInterceptor" />
<interceptor-ref name="alias" />
<interceptor-ref name="params" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params" />
<!-- excludes base CRUD methods from the validation process -->
<!-- validation interceptor triggers the xml validation -->
<interceptor-ref name="validation">
<param name="validateAnnotatedMethodOnly">true</param>
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
<!-- ajax validation interceptor -->
<interceptor-ref name="jsonValidation">
<param name="excludeMethods">input</param>
</interceptor-ref>
<!-- workflow interceptor triggers programmatic validation (calls validate()) -->
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- the new custom stack will be the default one used in the sub packages. -->
<default-interceptor-ref name="imsDefaultStack" />
<!-- exception handling -->
<global-results>
<result name="error">/jsp/common/error.jsp</result>
<result name="securityError">/jsp/common/access-denied.jsp</result>
<result name="ldapError">/jsp/common/ldap-connection-error.jsp</result>
</global-results>
<!-- any unhandled exceptions will return the error page displaying the
message of the exception. -->
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception" />
<exception-mapping result="securityError" exception="com.sapienza.jail.exception.NoApplicationAccess" />
<exception-mapping result="ldapError" exception="com.sapienza.jail.exception.LDAPConnectionException" />
</global-exception-mappings>
</package>
</struts>
I am using annotation based action mapping in my class as following
@Results({
@Result(name="index", type="tiles", location="testPage"),
@Result(name = "redirect", location = "user/search-user!view", type = "redirectAction")
})
@Namespace("/web/public")
@Action
public class HomeAction extends BaseAction {
private static final Logger logger = Logger.getLogger(HomeAction.class);
private static final String SESSIONBASKET = "userSessionBasket";
//-------------------------------------------------------------------------
// Dependencies injected by spring via setters
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Constructor and methods
//-------------------------------------------------------------------------
public HomeAction() {
}
@Override
public String execute() {
if (isInHttpSession(SESSIONBASKET)){
getSession().removeAttribute(SESSIONBASKET);
}
return result(REDIRECT_RESULT);
}
//-------------------------------------------------------------------------
// Getters and Setters
//-------------------------------------------------------------------------
}
Been struggling with the upgrade from struts 2.3.16 to 2.3.20 for a while. Not sure we're facing the same problem, but, still, I'm sharing the resolution that worked for me.
The REST plugin actions, which should have been indexed by suffix using the conventions: e.g. struts.convention.action.suffix = Controller
Was not working at all after upgrading all the struts2-* jar files and xwork-core.jar
Nothing was printed in logs.
Finally, came across with this post: http://comments.gmane.org/gmane.comp.jakarta.struts.user/186383 "I had the same problem this morning after updating just the struts2 and xwork jar files. I updated the asm, asm-commons, asm-tree, and commons-lang3 jar files to those found in the struts-2.3.20-lib.zip file and the problem went away."
After upgrading the asm-*.jar, as well, the problems went away.
The only thing I could not understand, was that the 2.3.20 release, downgrades some jar files, like commons-validator to 1.3.1 (from 1.4.0) and common-collections to 1.3.1 (from 3.2.1).
Hope it helps your projects as well.
Cheers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With