Struts2 .action extension causing CSS, JavaScript and Struts Dojo to break
Asked Answered
I

1

10

We have been running on Struts 2.1.8 for some time and all Struts actions have been working as expected, i.e. href's to the Struts actions are rendered with the action name with no extension.

Here is the JSP code that set's up the links:

<ul id="top_menu">
  <li id="itemHome" class="active"><s:a action="viewHome">Home</s:a></li>
  <li><s:a action="viewSearch">Search</s:a></li>
  <li><s:a action="viewBookMarks">My Bookmarks</s:a></li>
  <li><s:a action="viewSupport">Support</s:a></li>
</ul>

The links rendered correctly to http://localhost/viewHome, http://localhost/viewSearch, etc. under 2.1.8

We just upgraded to Struts 2.2.1 (an have checked all versions from this up to v2.3.4.1) and are now seeing Struts actions links are rendering as http://localhost/viewHome.action, http://localhost/viewSearch.action, etc.

My research has shown that the general suggested solution is to use

<constant name="struts.action.extension" value=""/>

in struts.xml to remove the .action suffix. Whilst this makes the URLs render correctly it is causing an unexpected side effect. Struts now thinks every URL is an action including requests for .css, .png, etc.

My filter-mapping in web.xml has not changed. And although it sends /* to Struts we didn't see this behavior under 2.1.8

<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>/*</url-pattern>
</filter-mapping>

To counteract this I've had to use the excludePattern to stop Struts trying to treat these requests as actions.

<constant name="struts.action.excludePattern" value="/index.html,/images/.*,/js/.*,/css/.*"/>

Whilst this works, the last hurdle is that my logs are full of errors from Struts tags requests that are being handled as Struts actions. When I add these URI's to the exclude pattern then Struts Dojo tags don't seem to be working in some pages.

The parts of struts.xml affected are:

<constant name="struts.devMode" value="true" />
<!-- Set URL's to have no .action extension -->
<constant name="struts.action.extension" value=""/>
<constant name="struts.action.excludePattern" value="/index.html,/images/.*,/js/.*,/css/.*"/>

And an example of the Struts errors in the log is:

2012-09-26 17:12:57,984 [http-bio-8080-exec-9] ERROR org.apache.struts2.dispatcher.Dispatcher- Could not find action or result
/struts/dojo/struts_dojo.js
There is no Action mapped for namespace [/] and action name [struts_dojo.js] associated with context path []. - [unknown location]
    at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
    at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
    at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
    at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:501)
    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)

I'm not sure if the struts Dojo requests are real URI's or virtual or something else.

It feels at this point that I've jumped through quite a few hoops to fix what is essentially a simple problem of removing the .action extension from URL's given that going back to the 2.1.8 JAR solves everything but I'm determined to find a way forward if possible.

Any help is very much appreciated.

Inna answered 26/9, 2012 at 17:19 Comment(1)
Humm, it seems that a page is requesting the lib struts_dojo.js. Are you using the dojo plugin for Struts? It is deprecated. If not, can you provide the code that is requesting that library?Klina
P
19

Try to use struts action exstension with comma like this
<constant name="struts.action.extension" value=","/>.
From the struts2 properties file:

Used by the DefaultActionMapper You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do The blank extension allows you to match directory listings as well as pure action names without interfering with static resources, which can be specified as an empty string prior to a comma e.g. struts.action.extension=, or struts.action.extension=x,y,z,, struts.action.extension=action,,

Pycnometer answered 27/9, 2012 at 21:0 Comment(8)
That worked. Thank you Aleksandr. Once I added the comma so the line reads: <constant name="struts.action.extension" value=","/> everything went back to the pre-struts 2.2.1 behaviour. I also didn't need to explicitly exclude the static content with the <constant name="struts.action.excludePattern" value="/index.html,/images/.*,/js/.*,/css/.*"/> and was able to take that out as well.Inna
It also helps setting name="struts.action.extension" value=",action", so that .action as well as no suffix works.Jagatai
I'm not sure this problem is still there in 2.3.16; anyone can confirm ?Chelicera
@AndreaLigios: Struts2 v. 2.3.16 empty value for extension constant doesn't work.Pycnometer
Ok. I've used it with the regex patternMatcher and advanced wildcard mappings, and it was working fine. Changed now to "," and it works identically... but my static res are all external, so maybe it's that.Chelicera
I've tried it now in a project with the default patterMatcher, and it works like a charm, while "" will break like hell :) Nice catch !!Chelicera
As of 2.3.24 -- setting struts.action.extension= with no value just works. Having , does not work.Accident
@asyncwait: No, you are wrong. Take a look at DefaultActionMapper, it is same as before. You are probably have some other configuration that interferes with extension. See also WW-4418.Pycnometer

© 2022 - 2024 — McMap. All rights reserved.