PortletStateHolder in the JBoss PortletBridge and ConcurrentModificationException

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.

more Hints on the Perfomance problems with AjaxPortletBridge and FacesContextImpl

After some investigation we found strange things:
First of all, the JavaServer Faces 1.2 Spec says:

getELContext
If the Collection returned by Application.getELContextListeners() is non-empty, create an instance of ELContextEvent and pass it to each ELContextListener instance in the Collection by calling the ELContextListener.contextCreated(javax.el.ELContextEvent) method

But not all Implementations of FacesContext are Spec conform.  JBoss 4.2.3 GA is delivered with the JSF Version called Mojarra which is the RI implementation of Sun. The facesContext of this Implementation does contain a getElContext method without a loop which calls contextCreated:

public ELContext getELContext(){
   assertNotReleased();
   if(elContext == null){
      elContext = new ELContextImpl(getApplication().getELResolver());
      elContext.putContext(javax/faces/context/FacesContext, this);
      UIViewRoot root = getViewRoot();
      if(null != root){
            elContext.setLocale(root.getLocale());
      }
   }
return elContext;
}

On the other hand the FacesContext delivered with the JBossPortletBridge and the FacesContext implementation of MyFaces are spec conform. They implement a loop which calls contextCreated of the bridge.

The high invocation count of FacesContext.getELContext() is caused by the UI base classes eg. UIComponent and UIViewRoot.
These classes are calling getELContext() very frequently and they are the root of most JSF Tags.
This is the reason for our abnormal cpu usage.

Unfortunately, we are not able to say which impact our empty implementation of contextCreated has. We don’t know which objects the ELContext need and for what.

AjaxPortletBridge, FacesContext and the lack of perfomance in JBoss Portal with Faces 1.2

These days my colleague Markus and me found a lack of perfomance in the JBossPortletBridge V.: 1.0.0.B6 .
We wonder about excorbitant CPU (  9 million calls / 150 page hits) usage by the contextCreated method of the Bridge:

public void contextCreated(ELContextEvent event) {
   // Add the portletConfig to the ELContext
   ELContext elContext = event.getELContext();
   if (elContext.getContext(PortletConfig.class) == null) {
      elContext.putContext(PortletConfig.class, portletConfig);
   }
}

The method is lightweight, but it is called very often (for every JSF tag) by the getELContext method of the FacesContext class. ContextCreated() is an implementation of the interface ELContextListener which is called in getELContext() of FacesContext. It doesn’t matter which implementation of FacesContextImpl is used, all Versions of Sun, Apache (myfaces-impl-1.2.6.jar) and JBoss (portletbridge-impl-1.0.0.B6.jar) call ELContextListener.ContextCreated() in a loop, which is called for every JSF-tag on each called website:

public ELContext getELContext() {
.....
   //notify ELContextListener that we have created this context
   ELContextListener[] listeners = application.getELContextListeners();
   if (listeners.length > 0){
     ELContextEvent event = new ELContextEvent(this.elContext);
     for (ELContextListener listener:listeners){
        listener.contextCreated(event);
     }
    }
.....
}

This loop is implemented since Faces 1.2.
However our webservers reached a cpu usage near 100% so we hadto find a way out… By using the “try and error” technique we found a solution:
We simply made an empty implementation of AjaxPortletBridge.contextCreated(). The result is stunning, we can’t find any impact on the application behaviour and the cpu usage is down to 10% 🙂
The simple question is what does AjaxPortletBridge.contextCreated() do? Is it really needed in all cases?

While searching Jira we found the following issue PORTLETBRIDGE-2 which does not really help.
I will ask the JBoss PortalBridge forum..