In my testing on Confluence 8.0.0-beta1, version 1.5.2 of the compat-lib is experiencing failures in ActionContextCompatManager#
initialiseActionContextCompat in the new code for this bug fix.
ClassNotFoundException for org.apache.struts2.dispatcher.HttpParameters. This happens in a new Class.forName() call added for this bugfix, I believe.
It is failing in the ActionContextStruts2AndWWCompat constructor.
The Class.forName("org.apache.struts2.dispatcher.HttpParameters") call is failing:
if ("com.opensymphony.xwork2.ActionContext".equals(actionContextClass)) {
this.setParameters = this.getACStruts2Method("setParameters", classLoader, Class.forName("org.apache.struts2.dispatcher.HttpParameters"));
} else {
this.setParameters = this.getACStruts2Method("setParameters", classLoader, Map.class);
}
That Class.forName() call throws a ClassNotFoundException for org.apache.struts2.dispatcher.HttpParameters which is caught by the ActionContextCompatManager#initialiseActionContextCompat
The the ActionContextCompatManager#initialiseActionContextCompat implementation mistakenly assumes that a ClassNotFoundException would be caused by calling Class.forName("com.opensymphony.xwork2.ActionContext). In this case, that Class.forName() call succeeded and then the ActionContextStruts2AndWWCompat constructor was called and THAT thing had code in it that threw a ClassNotFoundException. That try/catch needs to be narrowed down, IMO.
You can see that in the implementation of initialiseActionContextCompat:
private ActionContextCompat initialiseActionContextCompat(ClassLoader classLoader) {
ActionContextStruts2AndWWCompat internalDelegate;
try {
Class.forName("com.opensymphony.xwork2.ActionContext", false, classLoader);
internalDelegate = new ActionContextStruts2AndWWCompat("com.opensymphony.xwork2.ActionContext", classLoader);
} catch (ClassNotFoundException var6) {
log.debug("Could not find struts2 ActionContext, falling back to webwork ActionContext", var6);
try {
internalDelegate = new ActionContextStruts2AndWWCompat("com.opensymphony.xwork.ActionContext", classLoader);
} catch (ReflectiveOperationException var5) {
throw new ServiceException("ActionContext couldn't be initialized.", var5);
}
} catch (ReflectiveOperationException var7) {
throw new ServiceException("ActionContext couldn't be initialized.", var7);
}
return internalDelegate;
}
I am seeing this by turning on DEBUG logging for the package com.atlassian.confluence.compat.struts2.actioncontext so that I can see the debug logline for "Could not find struts2 ActionContext, falling back to webwork ActionContext" and the ClassNotFoundException.
2022-11-15 20:21:19,657 DEBUG [http-nio-8090-exec-31] [compat.struts2.actioncontext.ActionContextCompatManager] initialiseActionContextCompat Could not find struts2 ActionContext, falling back to webwork ActionContext
-- page: 98393 | referer: https:java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.HttpParameters not found by com.nearinfinity.confluence.survey-plugin [314]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1585)
at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1970)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at com.atlassian.confluence.compat.struts2.actioncontext.ActionContextStruts2AndWWCompat.<init>(ActionContextStruts2AndWWCompat.java:50)
at com.atlassian.confluence.compat.struts2.actioncontext.ActionContextCompatManager.initialiseActionContextCompat(ActionContextCompatManager.java:34)
at com.atlassian.confluence.compat.struts2.actioncontext.ActionContextCompatManager.lambda$new$0(ActionContextCompatManager.java:27)
at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:183)
at com.atlassian.confluence.compat.struts2.actioncontext.ActionContextCompatManager.get(ActionContextCompatManager.java:215)
at org.hivesoft.confluence.macros.survey.AddCommentAction.execute(AddCommentAction.java:121)
...
...
...
SO...
I think that try/catch for ClassNotFoundException in ActionContextCompatManager#initialiseActionContextCompat needs to be narrowed in scope. Also, and more importantly, do what it takes to make Confluence allow the Class.forName() call to work for org.apache.struts2.dispatcher.HttpParameters when a plugin is initializing ActionContextCompatManager
Here is my plugin code that explodes the initializer:
Map requestMap = ((Map) actionContextCompatManager.get("request"));
Per https://confluence.atlassian.com/doc/struts-2-upgrade-1155473773.html this is what the plugins add to pom.xml for dependencies when using the compat-lib for the struts2 migration:
<plugin>
{{ <groupId>com.atlassian.maven.plugins</groupId>}}
<artifactId>amps-maven-plugin</artifactId>
<configuration>
<instructions>
<DynamicImport-Package>
com.opensymphony.xwork;resolution:=optional,
com.opensymphony.webwork;resolution:=optional,
org.apache.struts2;resolution:="optional",
com.opensymphony.xwork2;resolution:="optional"
</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
Thank you @Kusal, that helped. I no longer have a problem using the compat-lib