-
Notifications
You must be signed in to change notification settings - Fork 812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WW-5382 Fix stale injections in Dispatcher #826
Conversation
Need to test this further in a staging environment and will improve test coverage to prevent similar regressions from reoccurring |
bda8f01
to
b9e3c5e
Compare
b9e3c5e
to
fa5b46c
Compare
fbd32f3
to
2c5087e
Compare
2c5087e
to
946737c
Compare
@@ -51,10 +51,6 @@ public void setUp() throws Exception { | |||
@After | |||
public void tearDown() throws Exception { | |||
XWorkTestCaseHelper.tearDown(configurationManager); | |||
configurationManager = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary
@@ -325,12 +325,8 @@ public Class<? extends Configuration> type() { | |||
} | |||
|
|||
protected ActionContext setContext(Container cont) { | |||
ActionContext context = ActionContext.getContext(); | |||
if (context == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is only called twice, and it is always null on the first call, and never null on the second call. I can't see why we wouldn't want to replace the bootstrap context once the final context has been constructed. Although it is also unclear if the ActionContext is even used after this point - i.e. for loading the PackageProviders. The ActionContext is cleared once the PackageProviders are loaded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest I would love to re-organise the whole proces. I assume the ActionContext
is only needed when serving an action, it should be created just before and destroyed just after.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that would be ideal - if that were the case we'd be able to remove the need for the bootstrap context too it looks like
@@ -192,6 +194,11 @@ public class Dispatcher { | |||
* Store ConfigurationManager instance, set on init. | |||
*/ | |||
protected ConfigurationManager configurationManager; | |||
private ObjectFactory objectFactory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should save some computation by injecting these beans once when the Dispatcher is initialised instead of constantly retrieving them from the container
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe they should be moved into constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the Dispatcher itself is not container-managed, we can't use constructor injection for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't have to be, just using container.inject(Dispatcher.class)
will create a new instance and injects all the dependencies. Anyway this would be a bit out of scope for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep would require a major refactor, I've got some ideas but not a high priority right now, as long as everything works
@@ -988,18 +1031,7 @@ protected boolean isMultipartRequest(HttpServletRequest request) { | |||
* @return a multi part request object | |||
*/ | |||
protected MultiPartRequest getMultiPartRequest() { | |||
MultiPartRequest mpr = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remnants from before the bean aliasing functionality existed I presume?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... good question, no idea :)
} | ||
} | ||
if (injectedContainer != ContainerHolder.get()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the core change of this PR - we compare the retrieved container instance against the one we last injected this with, and if it has changed, reinject
public static void tearDown() throws Exception { | ||
Dispatcher.setInstance(null); | ||
public static void tearDown(Dispatcher dispatcher) { | ||
if (dispatcher != null && dispatcher.getConfigurationManager() != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this here for better reuse
/** | ||
* Test case for Dispatcher. | ||
*/ | ||
public class DispatcherTest extends StrutsInternalTestCase { | ||
public class DispatcherTest extends StrutsJUnit4InternalTestCase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upgraded to JUnit4 and replaced older mocks with Mockito
} | ||
|
||
@Test | ||
public void dispatcherReinjectedAfterReload() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New test for reinjection functionality
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Changed line-endings to LF
for this file)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same deal with line-endings
Quality Gate passedThe SonarCloud Quality Gate passed, but some issues were introduced. 8 New issues |
I've now tested this fix with the Confluence DC test suite and did some additional manual sanity testing and all seems to be as expected now. Following a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks ok, left a few comments
@@ -325,12 +325,8 @@ public Class<? extends Configuration> type() { | |||
} | |||
|
|||
protected ActionContext setContext(Container cont) { | |||
ActionContext context = ActionContext.getContext(); | |||
if (context == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest I would love to re-organise the whole proces. I assume the ActionContext
is only needed when serving an action, it should be created just before and destroyed just after.
@@ -192,6 +194,11 @@ public class Dispatcher { | |||
* Store ConfigurationManager instance, set on init. | |||
*/ | |||
protected ConfigurationManager configurationManager; | |||
private ObjectFactory objectFactory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe they should be moved into constructor?
@@ -988,18 +1031,7 @@ protected boolean isMultipartRequest(HttpServletRequest request) { | |||
* @return a multi part request object | |||
*/ | |||
protected MultiPartRequest getMultiPartRequest() { | |||
MultiPartRequest mpr = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... good question, no idea :)
WW-5382
I understand most applications do not reload configuration after startup - but for applications that do, this is a critical bug as it means stale configuration persists after a reload. This extends to the
SecurityMemberAccess
policy which is now container injected.