Michael Müller wrote:
additionally, there's a problem/bug with performParentAction() in WOComponent: before the actual parentAction gets called via parent.valueForKey(action), WOF calls pushValuesToParent(). In case of stateless components this method also prematurely resets the component and returns the component instance to the component instance pool. :(
I can confirm that: all my stateless component problems where related to WOComponent calls to pushValuesToParent() performed from calls to performParentAction(String). This is a very nasty bug in WebObjects which can leads to data exchange between threads and sessions in an application instance that allows concurrent request handling. :-(
So, in case of concurrent request handling it is absolutely possible that your component instance gets checked out from the component instance pool while your parent action is called. Two separate threads would use the same instance of your component concurrently. Sad, but it's like that and it's a bug. Of course, the probability to experience this bug rises with the load on your application and the duration to perform the actual parent action.
Exactly.
I reported this bug nearly three years ago to Apple, along with a simple test application and a JMeter configuration script to reproduce it reliably. After a year or so I gave up on periodically watching the bugreport for changes or comments. Probably it hasn't been read until now. ;)
Our simple workaround then was to directly use
parent().valueForKey(actionName)
instead of
performParentAction(actionName).
By this means the problematic pushValuesToParent() doesn't get called in a place where it isn't meant to be and everything's fine. (At least, as long as your stateless components are non-synchronizing. Luckily, in our case, they were.)
Yes, this workaround works very well: since I've released this to production, I get no more exceptions and errors with my stateless components. I generally use a WOComponent subclass as superclass of all my components, so it's easier to overload the performParentAction(String) method to fix that:
public WOActionResults performParentAction(String actionName) {
WOActionResults results;
WOComponent parent;
parent = parent();
if(parent != null) {
if(!isStateless()) {
results = super.performParentAction(actionName);
} else {
results = (WOActionResults)parent.valueForKey(actionName);
}
} else {
throw new IllegalStateException("Can't find a parent for the current component.");
}
return(results);
}
Thank you very much!