While looking through my logfiles, I found a ConcurrentModificationException in the PortletStateHolder of JBoss PortletBridge Version 1.0.0.CR1:
15:45:41,176 WARN () [ContainerBase] Exception processing manager org.apache.catalina.session.StandardManager@8d386e background process java.util.ConcurrentModificationException at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:365) at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:376) at org.jboss.portletbridge.application.PortletStateHolder. removeSessionStates(PortletStateHolder.java:223) at org.jboss.portletbridge.application.PortletStateHolder. access$200(PortletStateHolder.java:57) at org .jboss.portletbridge.application.PortletStateHolder $WindowIDRetriver.valueUnbound(PortletStateHolder.java:291) at org.apache.catalina.session.StandardSession. removeAttributeInternal(StandardSession.java:1649) at org.apache.catalina.session.StandardSession. expire(StandardSession.java:756) at org.apache.catalina.session.StandardSession. isValid(StandardSession.java:592) at org.apache.catalina.session.ManagerBase. processExpires(ManagerBase.java:681) at org.apache.catalina.session.ManagerBase. backgroundProcess(ManagerBase.java:666) at org.apache.catalina.core.ContainerBase. backgroundProcess(ContainerBase.java:1315) at org.apache.catalina.core.ContainerBase$ ContainerBackgroundProcessor.processChildren(ContainerBase.java:1600) at org.apache.catalina.core.ContainerBase$ ContainerBackgroundProcessor.processChildren(ContainerBase.java:1609) at org.apache.catalina.core.ContainerBase$ ContainerBackgroundProcessor.processChildren(ContainerBase.java:1609) at org.apache.catalina.core.ContainerBase$ ContainerBackgroundProcessor.run(ContainerBase.java:1589) at java.lang.Thread.run(Thread.java:595)
This is a common Exception which is mostly thrown if an iterator is manipulated while he is in use. A quick look at the code confirmed my suspicion:
private void removeSessionStates(String scopeId) { synchronized (states) { // Iterate over copy of the keys, so LinkedHashSet do not support // concurrent modifications. for (Iterator keysIterator = states.keySet().iterator(); keysIterator .hasNext();) { StateId key = keysIterator.next(); if (key.getScopeId().equals(scopeId)) { keysIterator.remove(); } } } }
The developer saw the problem, but forgot to make the copy of the iterator..
To fix the problem you can code copy the class and fix the method:
private void removeSessionStates(String scopeId) { synchronized (states) { // collect the ids of the states which should be removed ArrayList toDelKeys = new ArrayList(10); for (StateId stateId : states.keySet()) { if (stateId.getScopeId().equals(scopeId)) { toDelKeys.add(stateId); } } // delete them for (StateId stateId : toDelKeys) { states.remove(stateId); } } }
Then you have to code copy the PortletBridgeBase and change all instances of PortletStateHolder
to your class.
Then you have to configure your web aplications to use a custom PortletBridge. Add
<context-param> <param-name>javax.portlet.faces.renderPolicy</param-name> <param-value>NEVER_DELEGATE</param-value> </context-param> <context-param> <param-name>javax.portlet.faces.BridgeImplClass</param-name> <param-value>de.koelnerwasser.portlet.bridge.MyPortletBridge</param-value> </context-param>
to the web.xml.
Stupidly i lost the password for my JBoss account, so i’m not able to add a Jira entry now . But I will do it next week.
Pingback: PortletStateHolder in the JBoss PortletBridge and ConcurrentModificationException | koelnerwasser.de