PSA - Confluence moves to Struts in 8.0 - EAP

Hi @ggautam,

It has been a couple of weeks–are there any Struts milestone releases planned in the near future? I see a couple of things that are particularly broken, such as the fact that the UPM doesn’t work at all (at least for me), which makes it difficult to even test a plugin .JAR (because the upload fails).

I was able to work around this by compiling QuickReload, uploading the QR JAR into a different version of Confluence, and then copying the database row for QR from the PLUGINDATA table in the old Confluence DB to the 8.0 DB, restarting 8.0, and then finally using QR to reinstall my test JAR via the filesystem…but it would be nice if there were an easier way.

Scott

Hi @ggautam,

Question 1 (to the community):

Is anyone else actually using the struts-m020 build? Has anyone been able to register an xwork action from a P2 context (versus an Atlassian-bundled plugin) and get it to work?

Question 2 (to Atlassian):

Is it possible to correct the sources published for the struts fork? I downloaded the sources labeled as “8.0.0-struts-m020” from MAC (link) but these do not appear to correspond to what is shipped.

For example, I was trying to figure out why none of my app’s xwork actions were recognized, so I started chasing down error messages like these that occur during plugin install:

2022-08-26 14:52:08,988 WARN [QuickReload - Plugin Installer] [confluence.plugin.descriptor.XWorkModuleDescriptor] buildAllowedMethodNames Could not find allowed methods specified for action pulp in namespace /pulp defined in plugin pulp

The XWorkModuleDescriptor in the shipped Confluence source archive does not contain any reference to this message, and that class still imports the legacy com.opensymphony.xwork.* packages, which did not seem right.

But if I look inside the Confluence .JAR actually shipped in the 8.0.0-struts-m020 milestone release, there is a completely-different implementation of XWorkModuleDescriptor that references xwork2.* and which has the warning I was hunting for.

Question/note 3 (to Atlassian):

The {attachments} macro is broken and it does not render at all…I did not see this in the list of already-tracked issues.

Scott

2 Likes

Hi @scott.dudley,

Thanks for reaching out with feedback.

The first build was most initial one for EAP and it had a lot of bugs. We are preparing another release scheduled for tomorrow and we will post an update here once its out. I have verified UPM working properly in the next potential EAP. Please find answers for questions asked below:

  • Question#2
    GG - we will look into the source path issue for custom EAP milestone as mentioned by you.
    For
  • Question #3
    GG - The new EAP milestone comes with a lot of fixes including fix for editor and attachments.
    Please stay tuned for tomorrow’s updates.

Thanks,
Ganesh

1 Like

Hi everyone,
We have published a new milestone for struts upgrade with major fixes. Please find the full highlights on Struts 2 upgrade page.

@scott.dudley - we have raised two issue in relation to the questions raised by you:

Please let us know if you face any issues or bugs with the milestone.

Thanks,
Ganesh

Hi @ggautam,

Thanks for the updated milestone! Thanks for your team’s work in fixing so many issues.

Here are the new issues discovered to date with struts-m027:

1- Is there any chance of fixing the plugin reinstall problem quickly (CONFSERVER-79847)? There are a ton of moving parts with 8.0, and the requirement to restart the entire instance to test any plugin change severely handicaps the dev loop. I am sensing nostalgia for P1 and Confluence 2.x…

2- The Space Tools->Content Tools link goes to the wrong place (it drops you somewhere in /pages/templates2, without the tabs and chrome, rather than in the expected part of space settings).

3- There is an undocumented breaking change in the declaration format of Xwork action method names. In <= 7.x, it was acceptable to write <action class="Whatever" method="foo"> without the “do” prefix, and Confluence would call Whatever.doFoo(). The declaration now requires the precise method name, so this must be changed to <action class="Whatever" method="doFoo">.

4- There is something flaky happening with VelocityUtils.getVelocityEngine(). It is inconsistently logging errors and returning a fresh engine. The implementation of this in 7.x was trivial and consistent (obtains from static object), but the new 8.x implementation tries to find the Struts dispatcher, then find the linked container, then get the VelocityManager, then grab a specific instance…and if all that doesn’t work, which it sometimes does not, it’s fishing things out of the ServletActionContext. And then it finally gives up with the behavior described above.

I can’t figure out a precise set of steps to reproduce, but it’s flaky. It might possibly be related to the plugin reinstall issues above. I also note that it works less frequently when it’s not on a HTTP thread context (ie. when there’s no fallback to fetching from the SAC). It also doesn’t work during system shutdown. This is perhaps less concerning because the system is shutting down, but the log errors in that case are ugly:

java.lang.IllegalStateException: The configuration manager shouldn't be null
	at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:1002)

5- The Attachments macro can now be used for general purposes, but if you double-click on the macro from within the editor to edit its configuration, the preview panel shows a NPE (something related to the ServletActionContext).

6- The logs get spammed with hundreds of warnings about allowed XWork action methods, referencing all Xwork-containing plugins installed. This happens any time the system starts, and even any time you (re)install a plugin that contains Xwork modules:

2022-08-30 12:49:24,483 INFO [Catalina-utility-1] [atlassian.plugin.manager.DefaultPluginManager] logTime Plugin system lateStartup ended
2022-08-30 12:49:24,642 WARN [lifecycle:thread-20] [expose.jmx.schedule.JmxInstrumentSchedulerImpl] onStart atlassian-instrumentation-jmx expose scheduler started.
2022-08-30 12:49:24,644 INFO [synchrony-interop-executor:thread-1] [plugins.synchrony.bootstrap.DefaultSynchronyProcessManager] startupSynchrony Starting Synchrony and enabling Collaborative Editing
2022-08-30 12:49:30,805 WARN [Catalina-utility-1] [confluence.plugin.descriptor.XWorkModuleDescriptor] buildAllowedMethodNames Could not find allowed methods specified for action applinks-space-admin in namespace /spaces defined in plugin applinks-space-admin
2022-08-30 12:49:30,806 WARN [Catalina-utility-1] [confluence.plugin.descriptor.XWorkModuleDescriptor] buildAllowedMethodNames Could not find allowed methods specified for action tinymce in namespace /plugins/tinymce defined in plugin tinymce

Scott

Hi everyone,
We have dropped another EAP(8.0.0-struts-m39) for Struts2, Please find the full highlights on Struts 2 upgrade page.

@scott.dudley please find the answers to each of your point below:

  1. CONFSERVER-79847([CONFSERVER-79767] Fix Space Tools, Templates page - Create and track feature requests for Atlassian products.) was a higher priority for us as well given its impact on plugins. Please let us know if you still face any issues with it.
  2. We have CONFSERVER-79767 in progress for this, please watch it for the updates.
  3. It is great observation, fortunately, we had a task for the same in Confluence core before we pushed the first milestone. We would update the Struts upgrade to accomodate this soon.
  4. We see one Velocity related item which touches upon dispatcher and the engine. We will try to reproduce your problem in that, please reach out if you find any concrete steps for reproduction. There are some quirks around ServletActionContext as ServletDispatcher was a Servlet in Webwork, while Struts’s StrutsPrepareFilter/StrutsExecuteFilter are ServletFilters which clears the Context and states.
  5. Please follow CONFSERVER-79907 to track AttachmentMacro feedback.
  6. We have just handled the logSpam, we would add some directions on allowed-methods parameter for XWork module with the next milestone. This is optional and is not needed for actions using execute or has method wiring.

Thanks,
Ganesh

@ggautam
I’m worried that there is an EAP release out there in the world (8.0.0-struts-m39) that breaks some of our plugins that are using xwork and does not provide the compat-lib that we need to unbreak them: [CONFSERVER-79630] Create compat-lib to handle basic compat API for Webwork/Struts - Create and track feature requests for Atlassian products.

One concern is that CONFSERVER-7936 is Priority=Low and I can imagine a world in which Atlassian goes ahead with an 8.x release that does not include the compat-lib because it is low priority. IMO, not delivering the compat-lib soon could damage partners.

Can somebody with the power please increase the priority of CONFSERVER-7936 and commit to delivering it ASAP? We have a Confluence EAP release that we are not testing for some of our plugins… because they fail to deploy… and we don’t have the time/resources to fork our code to write a backwards-incompatible solution that is testable on 8.0.0 but is not ever going to be delivered to our customers.

During this time that the EAP release is not testable by us there could be other problems piling up that we cannot detect. This could be risky.

Thanks!

Hi @turehoefner_appfire,

8.0.0-struts-m39 is specifically a Struts breaking change EAP and the whole point of the EAP is to allow developers to provide early feedback and also see the changes happening. Even thought the priority is lower with respect to other Struts items, I would want to assure you that its a struts-blocker as labelled in the ticket.

Compat lib with Struts work is in progress and there are internal PRs under review for the same. We are targeting to release it pretty soon.
I would like to highlight that we would try to cater to >90% of plugin’s cross-compatibility requirements.

Thanks,
Ganesh

Hi @ggautam,

Any change of escalating CONFSERVER-79848? I checked a recent source milestojne download (8.0.0-struts-m39) and there are no references whatsoever to “xwork2” anywhere in the entire source tree. Something seems not tagged correctly? Third-party developers really need access to certain parts of the Confluence source to understand how things work, so this is a significant impediment.

Thanks!
Scott

Hi @scott.dudley
We looked at CONFSERVER-79848 and it is caused by some infra issues which is slowing us down. We have taken your feedback and keeping it WIP in parallel, but given that we targeting merging of Struts to main EAP. This problem should soon go away.
Since the feature branch EAPs shown this issue, we will still fix the issue but with a lower priority.

Please let me know if that suits.

Thanks,
Ganesh

Hi @ggautam,

I could remove com.opensymphony.webwork and com.opensymphony.xwork imports from a shared library used in most of our apps. I did this by using com.atlassian.confluence.web.context.StaticHttpContext instead of com.opensymphony.webwork.ServletActionContext to retrieve the current request.

The library previously also used com.opensymphony.xwork.config.entities.ActionConfig to access action <param> values as defined in atlassian-plugin.xml.
I realized that xwork/struts actually provide an interceptor for this purpose, which is also configured, but not contained in any of the default interceptor stacks in Confluence’s xwork.xml:

<interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>

I’m planning to use the interceptor as follows in my actions:

	<xwork key="test-actions" name="Test Actions">
		<package name="test-actions" extends="default" namespace="/pages/test">
			<action name="test" class="test.TestAction" method="execute">
				<interceptor-ref name="defaultStack"/>
				<interceptor-ref name="static-params"/>
				<param name="SomeTestParam">this is injected into the action</param>
				<result name="success" type="velocity">/test-action.vm</result>
			</action>
		</package>
	</xwork>

And inside the action:

public class TestAction extends ConfluenceActionSupport {
    private String someTestParam;

    public String getSomeTestParam() {
        return someTestParam;
    }

    public void setSomeTestParam(String someTestParam) {
        this.someTestParam = someTestParam;
    }

    public String execute() {
        return SUCCESS;
    }
}

Could you confirm if both StaticHttpContext and this interceptor will continue to work in Confluence 8?
I think it would be important to keep the key of the interceptor as it currently is - which seems to be different from the xwork / struts defaults (which register it at staticParams; Confluence: static-params).
If Confluence 8 would register the new interceptor class from the xwork2 package with the same key static-params our apps would work with both Confluence 7 and 8.

That would help me a lot :slight_smile:

Thanks,
Jens

Hi @jens,
Thanks for reaching out.
Yes, StaticHttpContext will continue to work as is, it uses com.atlassian.core.filters.ServletContextThreadLocal internally and you can use that too if you need. We have mentioned something similar here in last week’s update.
The feedback for keeping the interceptors name same does make sense, because in some point in future, we would want our default package in struts.xml to rely on struts-default’s package which has different names. We would keep the old & new both names for compatibility so that your app could continue to work.
Since there is no way to deprecate the usage of XWork names, we would just put a comment for deprecation of old name like “static-params” and look at removing it in next major release.

Thanks,
Ganesh

1 Like

Thanks for confirming :slight_smile:

If you want to deprecate the non-standard names I think it would be a good idea to do that with Confluence 8.0.0 and introduce the replacements at the same time. This should be trivial because it’d only require duplicating the <interceptor> elements; but it would give us vendors the possibility to switch over to the new names when we drop support for Confluence 7, meaning we could support both 8.x and 9.x at the same time.

Cheers,
Jens

1 Like

@jens
Yes, duplication is the only way out for the moment. You can expect that the same, we had a discussion on it and agreed on the same earlier.
Which means you can expect both:

<interceptor name="static-params" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>

in Confluence 8.x

1 Like

Hi everyone,

The Confluence DC team merged Struts2 work to master and release a regular EAP 8.0.0-m69 early this week. This means we will now have only one EAP release at any moment for 8.0. Please read Oct 11 update for more details.

We thank you for all the feedback which helped in delivering this massive framework uplift. Please continue to reach out to us in case of any broken behaviour caused by Struts2.

Regards,
The Confluence DC Team

1 Like

Hi @ggautam,

We saw some unexpected changes in -m69, compared to the previous Struts release, with some previously-accessible classes no longer being exposed via OSGi.

For example, the following class was previously accessible to plugins in struts-m48 (and in all <8.0 Confluence releases):

com.atlassian.confluence.plugin.descriptor.PluginAwareActionConfig

It has now, however, been moved to the following location:

com.atlassian.confluence.impl.struts.PluginAwareActionConfig

None of the classes in impl.* seem to be exported (on purpose, I imagine). I understand the desire not to expose additional Confluence internals, but this is a class that had already been available for a long time, and it breaks a de-facto API that we had been using for the last 10 years. Can at least this class be moved somewhere where it is accessible to plugins?

Thanks!
Scott

Hi @ggautam ,

We’ve been using the confluence-compat-lib (v1.5.0) to address the discrepancies between webwork/Struts 2 and maintain compatibility for both Confluence 7 and 8.

We have been testing this on Confluence 8.0.0-m76.

However, we’ve noticed that when using ActionContextCompatManager, it fails at the method:

private ActionContextCompat initialiseActionContextCompat(ClassLoader classLoader)

because it attempts to initialise the setParameters method with an argument of type Map when in Struts 2, it’s actually of type HttpParameters. Refer to the 2 snippets below:

Initialisation code:

ActionContextStruts2AndWWCompat(String actionContextClass, ClassLoader classLoader) throws ReflectiveOperationException {
...
    this.setParameters = this.getACStruts2Method("setParameters", classLoader, Map.class);
...
}

Struts 2 ActionContext setParameters signature:

public void setParameters(HttpParameters parameters) {
    this.put("com.opensymphony.xwork2.ActionContext.parameters", parameters);
}

This causes the JVM to throw a NoSuchMethodException in runtime when it attempts the initialization of the ActionContextCompat.

Please help us clarify whether this is some intentional change we’ve missed the context of or whether it was an accidental oversight and if so, whether it would be addressed soon. We believe this is currently blocking us from using ActionContextCompatManager.

Hi @Zabed,

We recently received this feedback on the original compat issue and are working on getting setParameters compat-layer and you can track it under following issue: [CONFSERVER-80174] Fix for ActionContextCompatManager.setParameters method in compat-lib - Create and track feature requests for Atlassian products.

Thanks for raising it and please let me know if you have some questions.

Regards,
Ganesh

Hi @scott.dudley,
While we look at your request, can you please provide us the use case for this class for plugins?
cc: @Kusal

Thanks,
Ganesh

Hi @ggautam,

We are experiencing significant issues while trying to test on the latest milestones which include the Struts2 work. We have integrated the recently released compatibility lib. However, this does not solve our problem of being able to have custom actions that can be used across versions. We are seeking more information on how we can implement custom actions that are compatible with both Confluence 7.x.x and 8.x.x.

The docs recommend extending ConfluenceActionSupport. We’d effectively need two different base classes for 7 and 8, because ConfluenceActionSupport on 7.x.x extends com.opensymphony.xwork.ActionSupport and 8.x.x extends com.opensymphony.xwork2.ActionSupport.

This is a major issue for us as this breaks some of most popular macros. Can you please advise on how we can implement custom actions that are compatible with both 7 and 8?

Thanks!