[ http://issues.apache.org/jira/browse/MYFACES-750?page=all ]
Manfred Geiler resolved MYFACES-750:
------------------------------------
Fix Version: Nightly
Resolution: Fixed
Actually implemented a slightly different solution than was suggested. But
synchronized is the right solution here, Thanks!
> Need synchronization in LifecycleImpl
> -------------------------------------
>
> Key: MYFACES-750
> URL: http://issues.apache.org/jira/browse/MYFACES-750
> Project: MyFaces Core
> Type: Bug
> Components: Implementation
> Versions: 1.1.0
> Environment: Weblogic 8.1, AIX
> Reporter: Sam Schneider
> Assignee: Manfred Geiler
> Fix For: Nightly
>
> Getting this exception when removing a bean as a listener:
> java.util.ConcurrentModificationException
> at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:462)
> at java.util.AbstractList$Itr.next(AbstractList.java:433)
> at java.util.AbstractCollection.remove(AbstractCollection.java:268)
> at
> org.apache.myfaces.lifecycle.LifecycleImpl.removePhaseListener(LifecycleImpl.java:411)
> at
> com.erac.riskmgmt.ice.web.AbstractPageBean.afterPhase(AbstractPageBean.java:128)
> The method call at AbstractPageBean:128 is
> getLifecycle().removePhaseListener(this);
> protected Lifecycle getLifecycle() {
> String lifecycleId =
> getExternalContext().getInitParameter("javax.faces.LIFECYCLE_ID");
> if ((lifecycleId == null) || (lifecycleId.length() == 0)) {
> lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
> }
> LifecycleFactory lifecycleFactory = (LifecycleFactory)
> FactoryFinder.getFactory(
> FactoryFinder.LIFECYCLE_FACTORY);
> return lifecycleFactory.getLifecycle(lifecycleId);
> }
> Basically what's happening from a request perspective is that we have a
> custom ViewHandler that creates the backing bean that's registered for a
> given view id (custom registry using a HashMap that's created as a managed
> bean and maintained manually in faces-config). When the backing bean is
> created it adds itself as a listener and when the AFTER RENDER_RESPONSE is
> executed the bean removes itself as a listener (as above at line 128 in
> AbstractPageBean). No problems are observed in low-load situations, but when
> we sent the application to benchmarking simulating ~200 "concurrent" users we
> noticed this problem. It looks like easiest fix is to synchronize the array
> list on adding and removing listeners (currently we've worked around this by
> using an external lock to synchronize add/remove calls from our
> AbstractPageBean).
> However, It looks like there is also a potential problem with the call to
> getPhaseListeners() in that it creates a cached array that's later copied
> back into a *new* ArrayList in addPhaseListener(...) and
> removePhaseListener(...). Since there is no synchronization if someone
> called getPhaseListeners() and then two/N different threads tried to add
> listeners 1..N listeners could be lost (all would check for a null
> _phaseListenerList and multiple threads could potentially attempt to create a
> new _phaseListenerList and add/remove the PhaseListener) -- of course the
> converse problem would be that two/N different threads tried to remove phase
> listeners and the 1..N listeners would not be removed (they would be recopied
> in on another thread).
> What would simplify this whole business greatly would be to remove the cached
> list and simply synchronize on the ArrayList on the add/remove/getListeners:
> public void addPhaseListener(PhaseListener phaseListener)
> {
> if(phaseListener == null)
> {
> throw new NullPointerException("PhaseListener must not be null.");
> }
>
> // create _phaseListenerList at class scope -- so no more null-checks for it
> synchronized(_phaseListenerList) {
> _phaseListenerList.add(phaseListener);
> }
> }
> public void removePhaseListener(PhaseListener phaseListener)
> {
> synchronized(_phaseListenerList) {
> _phaseListenerList.remove(phaseListener);
> }
> }
> public PhaseListener[] getPhaseListeners()
> {
> synchronized(_phaseListenerList) {
> return (PhaseListener[])_phaseListenerList.toArray(new
> PhaseListener[_phaseListenerList.size()]);
> }
> }
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira