[ 
https://issues.apache.org/activemq/browse/CAMEL-2692?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=59225#action_59225
 ] 

Roland Knight commented on CAMEL-2692:
--------------------------------------

Yes, I am using the stock JDK 6 XML parser.

Turning debugging on reveals the underlying problem. It appears that Camel is 
calling Document.importNode from multiple threads on the same Document causing 
an ArrayIndexOutOfBounds error. This occurs in the converter and results in a 
null value. The stack trace for this error is below:

Thread [Camel Thread 9 - Split] (Suspended (exception 
ArrayIndexOutOfBoundsException))  
        Vector<E>.elementAt(int) line: 427      
        DeferredDocumentImpl.getNodeValueString(int, boolean) line: 1167        
        DeferredDocumentImpl.getNodeValueString(int) line: 1120 
        DeferredTextImpl.synchronizeData() line: 93 [local variables 
unavailable]       
        DeferredTextImpl(CharacterDataImpl).getNodeValue() line: 88     
        DocumentImpl(CoreDocumentImpl).importNode(Node, boolean, boolean, 
Hashtable) line: 1629 
        DocumentImpl(CoreDocumentImpl).importNode(Node, boolean, boolean, 
Hashtable) line: 1742 
        DocumentImpl(CoreDocumentImpl).importNode(Node, boolean, boolean, 
Hashtable) line: 1742 
        DocumentImpl(CoreDocumentImpl).importNode(Node, boolean) line: 1498     
        XmlConverter.toDOMDocument(Node) line: 572      
        NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not 
available [native method]  
        NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39      
        DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25  
        Method.invoke(Object, Object...) line: 597      
        ObjectHelper.invokeMethod(Method, Object, Object...) line: 772  
        InstanceMethodTypeConverter.convertTo(Class<T>, Exchange, Object) line: 
69      
        DefaultTypeConverter.doConvertTo(Class, Exchange, Object) line: 165     
        DefaultTypeConverter.convertTo(Class<T>, Exchange, Object) line: 91     
        DefaultMessage(MessageSupport).getBody(Class<T>, Object) line: 74       
        DefaultMessage(MessageSupport).getBody(Class<T>) line: 48       
        MoreoverTest$1$1.process(Exchange) line: 25     
        InstrumentationProcessor.process(Exchange) line: 67     
        TraceInterceptor(DelegateProcessor).processNext(Exchange) line: 53      
        TraceInterceptor(DelegateProcessor).proceed(Exchange) line: 82  
        TraceInterceptor.process(Exchange) line: 97     
        InstrumentationProcessor.process(Exchange) line: 67     
        DefaultErrorHandler(RedeliveryErrorHandler).processExchange(Exchange) 
line: 177 
        
DefaultErrorHandler(RedeliveryErrorHandler).processErrorHandler(Exchange, 
RedeliveryErrorHandler$RedeliveryData) line: 143      
        DefaultErrorHandler(RedeliveryErrorHandler).process(Exchange) line: 88  
        DefaultErrorHandler.process(Exchange) line: 49  
        DefaultChannel.process(Exchange) line: 228      
        DefaultErrorHandler(RedeliveryErrorHandler).processExchange(Exchange) 
line: 177 
        
DefaultErrorHandler(RedeliveryErrorHandler).processErrorHandler(Exchange, 
RedeliveryErrorHandler$RedeliveryData) line: 143      
        DefaultErrorHandler(RedeliveryErrorHandler).process(Exchange) line: 88  
        DefaultErrorHandler.process(Exchange) line: 49  
        Splitter(MulticastProcessor).doProcess(Processor, Processor, Exchange) 
line: 278        
        MulticastProcessor.access$000(MulticastProcessor, Processor, Processor, 
Exchange) line: 62      
        MulticastProcessor$1.call() line: 199   
        MulticastProcessor$1.call() line: 193   
        FutureTask$Sync.innerRun() line: 303    
        
SubmitOrderedCompletionService$SubmitOrderFutureTask(FutureTask<V>).run() line: 
138     
        ThreadPoolExecutor$Worker.runTask(Runnable) line: 886   
        ThreadPoolExecutor$Worker.run() line: 908       
        Thread.run() line: 619  


Inspection of the JDK getNodeValueString shows that this error can only occur 
if this function is called in parallel from two threads:
                for (int i = chunkCount - 1; i >= 0; i--) {                     
                                          
                    fBufferStr.append((String)fStrChunks.elementAt(i));
                }
                
                value = fBufferStr.toString();
                fStrChunks.removeAllElements();

One thread is looping over fStrChunks, while the other thread clear it via 
removeAllElements.


> Multithreading bug: getBody sporadically returns null
> -----------------------------------------------------
>
>                 Key: CAMEL-2692
>                 URL: https://issues.apache.org/activemq/browse/CAMEL-2692
>             Project: Apache Camel
>          Issue Type: Bug
>          Components: camel-core
>    Affects Versions: 2.3.0
>         Environment: Windows 7 64 bit, JDK 1.6.0_20
>            Reporter: Roland Knight
>            Assignee: Claus Ibsen
>         Attachments: news_20100502000001.zip
>
>
> Note that the only workaround for this bug is to remove the 
> parallelProcessing() call in the builder.
> I have a simple route that processes a file by splitting on a tag and 
> processing the DOM of each split message. The problem is that getBody is 
> randomly returning null but ONLY when using the parallelProcessing feature of 
> split. For some runs of the same XML file, the error does not occur at all 
> (the file is about 2MB of data), others it will happen once or twice. I am 
> currently using the latest 2.3-SNAPSHOT. 
> Also note, that after detecting the null, I tried calling 
> getBody(String.class) - this also may return null. Sometimes it does return 
> the proper XML. 
> Route configuration that reproduces the problem (my input XML is about 2MB 
> with about 500 article tags): 
>         public void configure() throws Exception { 
>           from("file:D:/inbox") 
>             .split(new XPathBuilder("//article")) 
>               .parallelProcessing()                     // remove this line 
> getBody below never returns null 
>               .process(new Processor() { 
>                 public void process(Exchange exchange) throws Exception { 
>                   Message inMessage = exchange.getIn(); 
>                   org.w3c.dom.Document domDocument = 
> inMessage.getBody(org.w3c.dom.Document.class); 
>                   if (domDocument == null) { 
>                     log("Null body"); 
>                   } else { 
>                     // process DOM here 
>                   } 
>                 } 
>               }) 
>             .end() 
>         } 
>       }); 

-- 
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