The ConfigurationContext in Axis2-Kernal causes ConcurrentModificationException 
in Session-Scope and thus is not multithreading-able
------------------------------------------------------------------------------------------------------------------------------------

                 Key: AXIS2-3484
                 URL: https://issues.apache.org/jira/browse/AXIS2-3484
             Project: Axis 2.0 (Axis2)
          Issue Type: Bug
          Components: kernel
    Affects Versions: 1.3
         Environment: WinXP, Eclipse 3.3.1.1, Tomcat 5.5.23
            Reporter: Stein S
            Priority: Critical
             Fix For: 1.3


Hello,

I have found a problem with a ConcurrentModificationException in the class 
'org.apache.axis2.context.ConfigurationContext' of the Axis2-kernel. In my 
test-case, I work with a stateful webservice in session-scope and the 
addressing-module included.

My service-xml looks like this:

<serviceGroup>
    <service
            name="Beratungsservice"
            
class="de.is2.web.beratungsservice.service.BeratungsserviceLifeCycle"
                        scope="soapsession"
    >
        <description>Beratungsservice</description>
                <module ref="addressing"/>
        <messageReceivers>
            <messageReceiver
                mep="http://www.w3.org/2004/08/wsdl/in-out";
                
class="de.is2.web.gen.beratungsservice.service.BeratungsserviceMessageReceiverInOut"
            />
        </messageReceivers>
        <schema schemaNamespace="http://is2.de/prototype/Beratungsservice"/>

        <parameter 
name="ServiceClass">de.is2.web.beratungsservice.service.Beratungsservice</parameter>
        <parameter name="modifyUserWSDLPortAddress">true</parameter>        
                <parameter name="Traeger_RootConfig">/rootconfig.xml</parameter>
    </service>
</serviceGroup>         

The session-timeout in axis2.xml is set to 30 seconds (default).

To test the service, I am using 30 client-threads, which send parallel calls to 
the service. 

private static void testMultiCall() {
        for(int index = 0; index < 30; index++) {
            try {
                Thread.sleep(100);
            }
            catch (InterruptedException oEx) {
                oEx.printStackTrace();
            }
            try {
                new Thread(new TestRunner(index), "T" + index).start();
            }
            catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }

Sometimes, I get ConcurrentModificationException  on server-side as shown 
below: 

java.util.ConcurrentModificationException
        at java.util.Hashtable$Enumerator.next(Hashtable.java:1020)
        at java.util.Hashtable$Enumerator.next(Hashtable.java:1020)
        at 
org.apache.axis2.context.ConfigurationContext.cleanupServiceGroupContexts(ConfigurationContext.java:591)
        at 
org.apache.axis2.context.ConfigurationContext.fillServiceContextAndServiceGroupContext(ConfigurationContext.java:232)
        at 
org.apache.axis2.engine.DispatchPhase.loadContexts(DispatchPhase.java:183)
        at 
org.apache.axis2.engine.DispatchPhase.checkPostConditions(DispatchPhase.java:95)
        at org.apache.axis2.engine.Phase.invoke(Phase.java:308)
        at org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:212)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:132)
        at 
org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
        at 
org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:120)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
        at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
        at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
        at 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
        at 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
        at 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at 
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
        at 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
        at 
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
        at 
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
        at 
org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
        at 
org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
        at 
org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
        at 
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
        at java.lang.Thread.run(Thread.java:595)

The exception is thrown in the method 'cleanupServiceGroupContexts()' at the 
line 'String sgCtxtId = (String) sgCtxtMapKeyIter.next();'

  private void cleanupServiceGroupContexts() {
        if (serviceGroupContextMap == null) {
            return;
        }
        long currentTime = new Date().getTime();
        for (Iterator sgCtxtMapKeyIter = 
serviceGroupContextMap.keySet().iterator();
             sgCtxtMapKeyIter.hasNext();) {
            String sgCtxtId = (String) sgCtxtMapKeyIter.next();
            ServiceGroupContext serviceGroupContext =
                    (ServiceGroupContext) serviceGroupContextMap.get(sgCtxtId);
            if ((currentTime - serviceGroupContext.getLastTouchedTime()) >
                getServiceGroupContextTimoutInterval()) {
                sgCtxtMapKeyIter.remove();
                cleanupServiceContexts(serviceGroupContext);
                contextRemoved(serviceGroupContext);
            }
        }
    }

When ever a new session is established, the axis-kernel checks the context for 
timed-out sessions an perform a clean-up. 
It seems, that the reason for the problem is the iterator of the keyset, which 
is not synchronised and thus, not prepared for multiple modification in 
different threads.

In my tests, I have temporary modified the method 
'cleanupServiceGroupContexts()' and synchronized  the member 
'serviceGroupContextMap'  as following:

private void cleanupServiceGroupContexts() {
        if (serviceGroupContextMap == null) {
            return;
        }
        long currentTime = new Date().getTime();
        
        synchronized (serviceGroupContextMap) {
            
            for (Iterator sgCtxtMapKeyIter = 
serviceGroupContextMap.keySet().iterator();
                 sgCtxtMapKeyIter.hasNext();) {
                String sgCtxtId = (String) sgCtxtMapKeyIter.next();
                ServiceGroupContext serviceGroupContext =
                        (ServiceGroupContext) 
serviceGroupContextMap.get(sgCtxtId);
                if ((currentTime - serviceGroupContext.getLastTouchedTime()) >
                    getServiceGroupContextTimoutInterval()) {
                    sgCtxtMapKeyIter.remove();
                    cleanupServiceContexts(serviceGroupContext);
                    contextRemoved(serviceGroupContext);
                }
            }            
        }        
    }

That synchronisation seems to solve the problem and no more 
ConcurrentModificationException are thrown.

Is this problem known so far? 
Have I done the proper modification to fix the bug?
Is there a bug-fix in the next release possible?

Thanks
S. Stein

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to