2

There are two actions and the *_* is in front of **(it doesn't matter at all that the default namespace does its work after specific namespace(unless the specific namespace extends it))

<package name="default" namespace="" extends="struts-default"></package>
<package name="admin" namespace="/admin" extends="default">
    <global-results>
       <result>/admin/result.jsp</result>
    </global-results>
    
    <action name="login" class="org.cc.action.AdminAction">
       <result>/admin/admin.jsp</result>
    </action>
    <action name="*_*" class=org.cc.action.{1}Action" method="{2}">
    </action>
</package>

<package name="error" namespace="" extends="default">
   <action name="**" >
     <result>/error.jsp</result>
   </action>
</package>

There is a error page I defined for catching the action that doesn't exist

Then I tested the action like

localhost:8080/myProjectName/admin/AdminAction.action

(it doesn't exist)

But it was caught by the action named "*_*" because an exception showed that AdminActionAction.class was not found.

Then I used the *__*(there are two '_'). It worked well and showed the error.jsp.

the format like "*a*" or "*#*" didn't work either that they would catch any action even if there is no a and # in the name of the action.

I use Struts 2.3.4.

Is there any document said between * and * there must be at least two characters or it will be just like *?

and here is the detail of the exception

Unable to instantiate Action, org.cc.action.AdminActionAction,  defined for     'AdminAction' in namespace '/admin'org.cc.action.AdminActionAction
com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:319)
com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:400)
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194)
org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:501)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)


java.lang.ClassNotFoundException: org.cc.action.AdminActionAction
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
com.opensymphony.xwork2.util.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:152)
com.opensymphony.xwork2.ObjectFactory.getClassInstance(ObjectFactory.java:108)
com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:161)
com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:151)
com.opensymphony.xwork2.ObjectFactory.buildAction(ObjectFactory.java:121)
com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:300)
com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:400)
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194)
org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:501)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)

and it is really easy to see that

localhost:8080/myProjectName/admin/AdminAction.action

(it doesn't exist) was caught by

<action name="*_*" class="net.org.cc.{1}Action" method="{2}">
Roman C
  • 49,761
  • 33
  • 66
  • 176
fairjm
  • 1,115
  • 12
  • 26
  • 1
    Please show the full stacktrace/error message along with your full struts.xml (or best a minimal struts.xml that produces this error if you have a lot of actions defined). Also mention if the struts2-conventions plugin is in place or any other plugin. This very much sounds like an issue with `com.opensymphony.xwork2.util.WildcardHelper` (the default pattern matcher), this package has been well tested, however I created a new tests to assure myself there is no issue, the tests with your particular requirements passed. The issue is not there it can handle those patterns, as expected. – Quaternion Feb 17 '13 at 03:52
  • 1
    In your case it does not matter which pattern is "in front" of the other as they are in separate packages. I think package "" should be first because the more specific package will always be searched first, then it will fall back to "". Package "" is thus a sort of catch all, so having it first reminds you of its atypical behaviour. Of course this won't fix your issue just clearing up an unrelated misconception. – Quaternion Feb 17 '13 at 04:01
  • Now I use `Admin_*` instead of `*_*` to match the action like `Admin_add.action` `Admin_del.action` and so on.And when I hit `localhost:8080/myProjectName/admin/AdminAction.action(it doesn't exist)`,it works well showing the error.jsp.But my problem is why `*_*` can match `AdminAction.action(doesn't exist)'. – fairjm Feb 17 '13 at 08:19
  • This is appears to be a bug. I get the same behaviour too... strange. – Quaternion Feb 17 '13 at 08:29
  • 1
    Issue affects 2.3.8 as well. – Quaternion Feb 17 '13 at 08:52
  • Reported bug https://issues.apache.org/jira/browse/WW-3985 – Quaternion Feb 17 '13 at 11:22
  • @Quaternion I think it's just a compatibility issue, not the bug. – Roman C Feb 17 '13 at 11:43
  • @Roman C, it is a pretty ugly wart – Quaternion Feb 18 '13 at 04:36
  • Not good to use emoticons as Action names :o) – Andrea Ligios Feb 18 '13 at 11:09

2 Answers2

2

Registered a bug https://issues.apache.org/jira/browse/WW-3985, however a quick work around would be to use **_** this will provided the desired functionality

Quaternion
  • 10,380
  • 6
  • 51
  • 102
1

In the configuration above mapping was created with action name AdminAction and namespace /admin. That's why you'd gotten an exception because action config matchers found an action config for the patten "*_*". But it can't find it for the pattern "*__*" for the same action name. Thus fallback to the default namespace "" and in this namespace it matches "**" pattern as a result to error page.

Actually for this action name created two similar matcher and one of them did match. What the matcher is created and what pattern is used?

The default runtime comfiguration implementation uses the parameter looseMatch that is hardcoded to true. There's desctiption in the javadoc

Patterns can optionally be matched "loosely". When the end of the pattern matches *[^*]*$ (wildcard, no wildcard, wildcard), if the pattern fails, it is also matched as if the last two characters didn't exist. The goal is to support the legacy "*!*" syntax, where the "!*" is optional.

And as @Quaternion mentioned in the comment, the matcher with paterrn * added to the list. Anything else as described earlier.

Roman C
  • 49,761
  • 33
  • 66
  • 176
  • 1
    But it is really confusing that there is no `_` in the `AdminAction.action` but it is still matched by `*_*`. – fairjm Feb 17 '13 at 02:15
  • 1
    @RomanC The point is the pattern `*_*`, is being resolved as `*` there is no way that behaviour should be expected. Searching "" is documented. – Quaternion Feb 17 '13 at 11:02
  • Thx a lot.Could you show me the URL you got for more details. – fairjm Feb 17 '13 at 12:19
  • I read the [doc](http://struts.apache.org/release/2.2.x/docs/wildcard-mappings.html) on the site, but didn't find anything helpful, today I've found it in the source code. – Roman C Feb 17 '13 at 12:30
  • There's also [link](http://struts.apache.org/release/2.2.x/xwork-core/apidocs/com/opensymphony/xwork2/config/impl/AbstractMatcher.html) from the XWork API docs – Roman C Feb 17 '13 at 12:49