Uploaded image for project: 'Confluence Server'
  1. Confluence Server
  2. CONFSERVER-20055

Web sudo fails with NoSuchMethodException for constructor-injected plugin actions



    • Priority for beta phase:


      Steps to reproduce:

      1. Upload test-admin-action-plugin-1.0-SNAPSHOT.jar into Confluence 3.3-beta2.
      2. Ensure web sudo is enabled.
      3. Go to the test page, e.g. http://localhost:8080/confluence/admin/test/test.action
      4. You get the following exception:

      java.lang.NoSuchMethodException: Unable to load action: com.atlassian.confluence.plugin.test.TestAction
      	at com.opensymphony.xwork.config.entities.ActionConfig.getMethod(ActionConfig.java:115)
      	at com.atlassian.confluence.security.websudo.WebSudoInterceptor.intercept(WebSudoInterceptor.java:49)

      5. Disable web sudo.
      6. Go to the test page, e.g. http://localhost:8080/confluence/admin/test/test.action
      7. The action works if web sudo is disabled.

      I'm rating this as critical because it's a regression which will affect many Adaptavist plugins (the bug was discovered by Dan Hardiker). We've been recommending them to use constructor injection for a few years now, so this is a serious problem for them.

      Technical notes

      If you debug this, you see an InstantiationException like this:

      java.lang.InstantiationException: com.atlassian.confluence.plugin.test.TestAction
      	at java.lang.Class.newInstance0(Class.java:340)
      	at java.lang.Class.newInstance(Class.java:308)
      	at com.opensymphony.xwork.ObjectFactory.buildBean(ObjectFactory.java:97)
      	at com.opensymphony.xwork.ObjectFactory.buildAction(ObjectFactory.java:77)
      	at com.atlassian.confluence.plugin.ConfluencePluginObjectFactory.buildAction(ConfluencePluginObjectFactory.java:60)

      Some code in the WebSudoInterceptor actually results in a new (non-PluginAware) ActionConfig being instantiated by XWork, where the plugin classloader is not used to find the plugin class or autowire it properly.

      if (!getWebSudoManager().matches(requestURI, actionInvocation.getAction().getClass(), actionInvocation.getProxy().getConfig().getMethod()))
          return actionInvocation.invoke();

      Here is the implementation of getMethod() from ActionConfig which is called above:

      try {
          ActionConfig actionConfig = new ActionConfig(null, getClassName(), null, null, null);
          Action action = ObjectFactory.getObjectFactory().buildAction(actionConfig);
          clazz = action.getClass();
      } catch (Exception e) { // TODO: Only doing this because buildAction() throws Exception
          throw new NoSuchMethodException("Unable to load action: " + e.getMessage());

      Notice that a new ActionConfig is created here and passed to ConfluencePluginObjectFactory.buildAction(). When this method is called with a non-PluginAware ActionConfig, XWork ends up calling Class.newInstance() which only works for actions which don't use constructor injection.

      We need to change the WebSudoInterceptor to use a way of finding the Method that doesn't construct a new ActionConfig object. At this late stage in the release, I think a good start would be copying the mechanism from ActionConfig into the WebSudoInterceptor and use getMethodName() without loading the class this way.


          Issue Links



              • Assignee:
                mjensen Matthew Jensen
                matt@atlassian.com Matt Ryall
                Last Touched By:
                Owen Sanico
                Marlena Compton [Atlassian], Stefan Saasen
              • Votes:
                0 Vote for this issue
                2 Start watching this issue


                • Created:
                  Last commented:
                  7 years, 8 weeks, 1 day ago