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

Claus Ibsen updated CAMEL-24516:
--------------------------------
    Fix Version/s: 4.23.0

> AbstractCamelContext: keep TypeConverter non-null after stop; reset only on 
> restart
> -----------------------------------------------------------------------------------
>
>                 Key: CAMEL-24516
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24516
>             Project: Camel
>          Issue Type: Improvement
>            Reporter: mayur mohan
>            Priority: Minor
>              Labels: camel-base-engine, diagnostic
>             Fix For: 4.23.0
>
>
> h2. Problem
> {{AbstractCamelContext.forceStopLazyInitialization()}} sets 
> {{typeConverter}}, {{typeConverterRegistry}} and {{injector}} to {{null}} at 
> the tail of {{doStop()}}. Any async work still running on the reactive 
> executor at that point (e.g. a Multicast continuation, parallel Splitter 
> task, or Quartz SFTP poll) hits a bare {{NullPointerException}} at one of the 
> ~200 unguarded {{getTypeConverter()}} call sites across {{core/}}.
> {{DefaultReactiveExecutor.doStop()}} does no draining, so async continuations 
> are not guaranteed to have finished when the tail of {{doStop()}} runs -- 
> even when graceful route shutdown reports success.
> h2. Stack Trace Examples
> *Example 1 -- Quartz SFTP poll calling ExchangeHelper.convertToType():*
> {noformat}
> java.lang.NullPointerException: Cannot invoke 
> "org.apache.camel.TypeConverter.convertTo(java.lang.Class, 
> org.apache.camel.Exchange, Object)"
>     because the return value of 
> "org.apache.camel.CamelContext.getTypeConverter()" is null
>     at 
> org.apache.camel.support.ExchangeHelper.convertToType(ExchangeHelper.java:261)
>     at 
> org.apache.camel.support.AbstractExchange.getProperty(AbstractExchange.java:321)
>     at 
> org.apache.camel.support.DefaultExchange.getProperty(DefaultExchange.java:27)
>     at 
> com.sap.esb.camel.ftp.sap.sftp.component.SapSftpConsumer.isStopOnExceptionEnabled(SapSftpConsumer.java:189)
>     at 
> com.sap.esb.camel.ftp.sap.sftp.component.SapSftpConsumer.processBatch(SapSftpConsumer.java:172)
>     at 
> org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:206)
>     at 
> com.sap.esb.camel.ftp.sap.sftp.component.SapSftpConsumer.poll(SapSftpConsumer.java:134)
>     at 
> org.apache.camel.support.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:202)
>     at 
> org.apache.camel.support.ScheduledPollConsumer.run(ScheduledPollConsumer.java:116)
>     at 
> org.apache.camel.pollconsumer.quartz.QuartzScheduledPollConsumerJob.execute(QuartzScheduledPollConsumerJob.java:61)
>     at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
>     at 
> org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
> {noformat}
> *Example 2 -- Multicast async continuation calling AbstractExchange.getOut() 
> via BeanProcessor:*
> {noformat}
> java.lang.NullPointerException: Cannot invoke 
> "org.apache.camel.TypeConverter.convertTo(java.lang.Class, 
> org.apache.camel.Exchange, Object)"
>     because the return value of 
> "org.apache.camel.CamelContext.getTypeConverter()" is null
>     at 
> org.apache.camel.support.AbstractExchange.getOut(AbstractExchange.java:548)
>     at 
> org.apache.camel.support.DefaultExchange.getOut(DefaultExchange.java:27)
>     at 
> org.apache.camel.support.AbstractExchange.getMessage(AbstractExchange.java:569)
>     at 
> org.apache.camel.support.DefaultExchange.getMessage(DefaultExchange.java:27)
>     at 
> com.sap.gateway.ip.core.customdev.processor.IGWScriptProcessor.setAllAttachments(IGWScriptProcessor.java:595)
>     at 
> com.sap.gateway.ip.core.customdev.processor.IGWScriptProcessor.process(IGWScriptProcessor.java:305)
>     at jdk.internal.reflect.GeneratedMethodAccessor3818.invoke(Unknown Source)
>     at 
> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>     at java.base/java.lang.reflect.Method.invoke(Method.java:569)
>     at 
> org.apache.camel.support.ObjectHelper.invokeMethodSafe(ObjectHelper.java:403)
>     at org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:494)
>     at 
> org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:316)
>     at 
> org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:286)
>     at 
> org.apache.camel.component.bean.AbstractBeanProcessor.process(AbstractBeanProcessor.java:146)
>     at 
> org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:81)
>     at 
> org.apache.camel.support.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:104)
>     at 
> com.sap.it.op.agent.collector.camel.MplInterceptor$MplAsyncProcessor.process(MplInterceptor.java:290)
>     at 
> org.apache.camel.support.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:104)
>     at 
> org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:477)
>     at 
> org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.executeFromQueue(DefaultReactiveExecutor.java:224)
>     at 
> org.apache.camel.impl.engine.DefaultReactiveExecutor.executeFromQueue(DefaultReactiveExecutor.java:82)
>     at 
> org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.await(DefaultAsyncProcessorAwaitManager.java:96)
>     at 
> org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:85)
>     at 
> org.apache.camel.processor.MulticastProcessor$MulticastReactiveTask.lambda$run$1(MulticastProcessor.java:664)
>     at 
> org.apache.camel.util.concurrent.AsyncCompletionService$Task.run(AsyncCompletionService.java:162)
>     at 
> org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:193)
>     at 
> org.apache.camel.impl.engine.DefaultReactiveExecutor.schedule(DefaultReactiveExecutor.java:59)
>     at 
> org.apache.camel.processor.MulticastProcessor.lambda$schedule$1(MulticastProcessor.java:392)
>     at 
> java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
>     at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
>     at 
> java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
>     at 
> java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
>     at java.base/java.lang.Thread.run(Thread.java:840)
> {noformat}
> h2. Root Cause
> {{AbstractCamelContext.forceStopLazyInitialization()}} 
> ({{core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java}}):
> {code:java}
> protected void forceStopLazyInitialization() {
>     camelContextExtension.resetInjector();
>     camelContextExtension.resetTypeConverterRegistry();
>     camelContextExtension.resetTypeConverter(); // sets field to null
> }
> {code}
> h2. Fix
> Move the three null-and-recreate calls from {{forceStopLazyInitialization()}} 
> to the start of {{forceLazyInitialization()}}, guarded by {{firstStartDone}}. 
> The fields are nulled synchronously at the beginning of the next 
> {{doStart()}} instead of at the end of {{doStop()}}:
> - {{getTypeConverter()}} is never {{null}} during the stopped/idle window
> - All ~200 unguarded call sites fixed at once with no null-checks or sentinels
> - Restart-in-place ({{stop()}}/{{start()}} on the same instance) preserved
> h2. Related
> Supersedes CAMEL-24510 and CAMEL-24515 which attempted per-call-site fixes.
> h2. PR
> https://github.com/apache/camel/pull/25775



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to