[ 
https://issues.apache.org/jira/browse/CXF-2220?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Daniel Kulp updated CXF-2220:
-----------------------------

    Attachment: cxf-2220.patch


I really don't think that switching to the Executors.newSingleThreadExecutor() 
is a good idea.   It completely defeats the purpose of having the work queue.   
 I really think we SHOULD be able to fix this in the AutomaticWorkQueueImpl.  

I've attached a patch (I'll probably commit to 2.2.x if tests pass with it) 
that does a bunch of modifications to the AWQI:

1) Made it create it's own ThreadGroup - it tries to traverse up the parents of 
the current thread group to find the highest parent that it can use.   Thus, 
the resulting threads should be as close to "system" threads instead of 
application threads as possible.

2) Creates a ThreadFactory around that group.   It will set the 
contextClassLoader for each thread it creates to the classloader of the AWQI, 
not any application context classloaders.   

3) For each "Runnable" submitted to Execute, it wrappers it with a new Runnable 
that will make sure the contextClassLoader on the thread used to run the 
runnable is the same as the calling thread.    That should allow us to avoid 
modifying every place that something is submitted to the AWQI to have it do the 
classloader copy.

I hope the combination of the three will fix the issue for you.   Could you 
give it a run through with your tests and let me know how it goes?

Thanks!


> Heavily reused "default" Work Queue Problem
> -------------------------------------------
>
>                 Key: CXF-2220
>                 URL: https://issues.apache.org/jira/browse/CXF-2220
>             Project: CXF
>          Issue Type: Bug
>    Affects Versions: 2.2.1
>            Reporter: Richard Opalka
>            Assignee: Daniel Kulp
>         Attachments: cxf-2220.patch, HTTPConduit.diff
>
>
> Hi CXF Team,
>   We're fighting with threading+classloading related issues when testing 
> JBossWS-CXF integration.
> The problematic part is WorkQueueManagerImpl.getAutomaticWorkQueue() method 
> that
> is reused in the following three places in CXF code base.
> [/home/opalka][/home/opalka/THIRDPARTY/CXF/SVN/tags/cxf-2.2.1]>grep -r 
> getAutomaticWorkQueue * | grep -v "\.svn" | grep -v Test | grep -v workqueue
> rt/core/src/main/java/org/apache/cxf/interceptor/OneWayProcessorInterceptor.java:
>                 .getAutomaticWorkQueue().execute(new Runnable() {
> rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java:
>                     queue = mgr.getAutomaticWorkQueue();
> rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java:      
>                      :  workQueueManager.getAutomaticWorkQueue();
> This method constructs "default" worker threads pool on first request and 
> this thread pool is 
> heavily reused by CXF for other applications. We see the following problem on 
> our server side:
> When this "default" worker threads pool gets constructed all its worker 
> threads have associated
> classloader of the calling thread (in our case calling thread has associated 
> web application classloader).
> This is how Java threads are constructed (they inherit the parent thread 
> classloader).
> This thread pool is heavily reused by CXF for other applications.
> The problem will appear when we undeploy the web application (the one that 
> worker threads have associated
> classloader with). After undeployment of that archive all worker threads will 
> throw ClassNotFoundException when passed
> jobs will try to do something with the classloader. Here's the sample stack 
> trace:
> 2009-05-12 09:30:14,923 INFO  [org.apache.cxf.phase.PhaseInterceptorChain:70] 
> (pool-13-thread-2) Interceptor has thrown exception, unwinding now
> org.apache.cxf.binding.soap.SoapFault: Problems creating SAAJ object model
>       at 
> org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.handleMessage(SAAJInInterceptor.java:165)
>       at 
> org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.handleMessage(SAAJInInterceptor.java:67)
>       at 
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:236)
>       at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:641)
>       at org.apache.cxf.endpoint.ClientImpl$1$1.run(ClientImpl.java:722)
>       at 
> org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
>       at org.apache.cxf.endpoint.ClientImpl$1.onMessage(ClientImpl.java:720)
>       at 
> org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2134)
>       at 
> org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream$1.run(HTTPConduit.java:2018)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
>       at java.lang.Thread.run(Thread.java:595)
> Caused by: javax.xml.soap.SOAPException: Unable to create message factory for 
> SOAP: Unable to create SAAJ meta-factoryProvider 
> com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl could not be 
> instantiated: java.lang.IllegalStateException: 
> baseclassloa...@298b744f{vfszip:/opt/svn/jbossas/tags/JBoss_5_0_1_GA/build/output/jboss-5.0.1.GA/server/cts/tmp/jsr88/WSAsyncHandler_wsservlet_vehicle.ear/WSAsyncHandler_wsservlet_vehicle_web.war/}
>  classLoader is not connected to a domain (probably undeployed?) for class 
> com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl
>       at javax.xml.soap.MessageFactory.newInstance(Unknown Source)
>       at 
> org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.getFactory(SAAJInInterceptor.java:84)
>       at 
> org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.handleMessage(SAAJInInterceptor.java:96)
>       ... 11 more
> To prevent these kinds of problems I had to implement the patches to don't 
> reuse "default" worker threads pool.
> See attached HttpConduit.java patch how to achieve that.
> Could you apply the patch for all three CXF souce files where "default" 
> worker threads pool is reused?
> The solution is to use e.g. Executors.newSingleThreadExecutor() instead of 
> WorkQueueManagerImpl.getAutomaticWorkQueue() method.
> Thanks,
> JBossWS Team
> PS: BTW, it took many hours of heavy debugging to identify this issue :(

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

Reply via email to