0

I'm starting to use the Struts2 Rest Plugin in our Spring application. Let's start with our struts.xml:

<struts>
    <constant name="struts.devMode" value="true" />
    <constant name="struts.custom.i18n.resources" value="lang/messages" />
    <constant name="struts.ognl.allowStaticMethodAccess" value="true" />
    <constant name="struts.mapper.class" value="rest" />

    <package name="default">
        <action name="document" class="DocumentRestaction" />
    </package>
</struts>

Then in Spring, I'm doing the following (to see if the String is injected):

<bean name="DocumentRestaction" class="be.example.actions.DocumentRestaction">
    <property name="injected" value="Oh Hai" />
</bean>

I do a POST request to the URL /documents and end up in the create() method, great! In debug, my injected variable is injected. But when I let the debug continue, I get following exception:

4129 [http-8080-2] ERROR org.apache.struts2.rest.RestActionInvocation - Exception processing the result.
java.lang.RuntimeException: Invalid action class configuration that references an unknown class named [DocumentRestaction]
    at org.apache.struts2.convention.ConventionsServiceImpl.determineResultPath(ConventionsServiceImpl.java:100)
    at org.apache.struts2.convention.ConventionUnknownHandler.determinePath(ConventionUnknownHandler.java:379)
    at org.apache.struts2.convention.ConventionUnknownHandler.handleUnknownResult(ConventionUnknownHandler.java:268)
    at com.opensymphony.xwork2.DefaultUnknownHandlerManager.handleUnknownResult(DefaultUnknownHandlerManager.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.createResult(DefaultActionInvocation.java:227)
    at org.apache.struts2.rest.RestActionInvocation.executeResult(RestActionInvocation.java:221)
    at org.apache.struts2.rest.RestActionInvocation.processResult(RestActionInvocation.java:198)
    at org.apache.struts2.rest.RestActionInvocation.invoke(RestActionInvocation.java:146)
    at com.opensymphony.xwork2.DefaultActionProxy.execute(DefaultActionProxy.java:147)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:510)
    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:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:679)
Caused by: java.lang.ClassNotFoundException: DocumentRestaction
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
    at org.apache.struts2.util.ClassLoaderUtils.loadClass(ClassLoaderUtils.java:111)
    at org.apache.struts2.convention.ConventionsServiceImpl.determineResultPath(ConventionsServiceImpl.java:98)
    ... 27 more

But the class has been found .. (I ended up in create), why is it saying this? And most importantly, what am I doing wrong?

I'm using Spring v3.0.5, struts2-rest-plugin v2.3.1, struts2-core v2.3.1 and struts2-spring-plugin 2.3.1

Roman C
  • 49,761
  • 33
  • 66
  • 176
Bart Vangeneugden
  • 3,436
  • 4
  • 33
  • 52
  • Are you also using the S2 spring plugin? – Dave Newton Dec 21 '11 at 15:54
  • Yep, I forgot to mention that normal Struts actions work with Spring already – Bart Vangeneugden Dec 21 '11 at 16:01
  • Okay. Yeah, I suspect it's flailing when it tries to determine the result path, although I don't have an immediate workaround. I'd file a JIRA for this against the REST plugin if there isn't one already; it may be a known issue, but I don't have an answer at this point--someone will look in to it. – Dave Newton Dec 21 '11 at 16:04
  • Also, which version are you using? – Dave Newton Dec 21 '11 at 16:12
  • 1
    Confirmed; there's an apparent (one more thing to check) conflict between how the convention plugin looks up the result path (based on the class) and the spring plugin. Note that configuring via autowiring would likely eliminate the problem--I believe the issue happens specifically because you're configuring it in XML. – Dave Newton Dec 21 '11 at 16:43
  • Ah, thanks for looking this up! I'll try to configure it by using `properties` and autowiring and update my question with my results – Bart Vangeneugden Dec 22 '11 at 08:28
  • Ah, I solved the problem by removing the convention plugin! This is unnecessary as you're using Spring to instantiate your Class instances! – Bart Vangeneugden Dec 22 '11 at 08:32

1 Answers1

0

In case anyone is looking for a solution to this, this article might help.

There's an omission in the sample code given though - in your applicationContext.xml, make sure you define the "id" and "class" to be the fully qualified class name of your controller:

   <bean id="com.mersoft.web.controller.TestController" class="com.mersoft.web.controller.TestController">
      <constructor-arg ref="testManager" />
   </bean>

Hope that helps. Oh, and to be clear, you don't have to remove the convention plugin as suggested in an earlier comment.

shaunlim
  • 4,384
  • 6
  • 33
  • 38