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

mayur mohan updated CAMEL-24515:
--------------------------------
    Description: 
h2. Problem

{{AbstractExchange.getIn(Class<T>)}} and {{AbstractExchange.getOut(Class<T>)}} 
call {{context.getTypeConverter().convertTo(...)}} directly without a null 
guard. When {{CamelContext}} is shutting down, 
{{DefaultCamelContextExtension.resetTypeConverter()}} sets the type converter 
to {{null}} during {{forceStopLazyInitialization()}}. Any thread that calls 
these methods during that window gets a bare {{NullPointerException}} with no 
actionable message.

This is the same race condition as CAMEL-24510 (fixed in 
{{ExchangeHelper.convertToType}}), but affecting two additional call sites in 
{{AbstractExchange}} that bypass {{ExchangeHelper}} entirely.

h2. Root Cause

File: 
{{core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java}}

Line ~499 (getIn):
{code:java}
return context.getTypeConverter().convertTo(type, this, in);
{code}

Line ~553 (getOut):
{code:java}
return context.getTypeConverter().convertTo(type, this, out);
{code}

Note: {{getOut(Class<T>)}} is called from {{getMessage(Class<T>)}} which is 
used broadly by Camel processors and scripts.

h2. Stack Trace

{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. Fix

Add null guard on the {{TypeConverter}} in both methods, throwing 
{{IllegalStateException}} with a descriptive message instead of bare NPE:

{code:java}
TypeConverter tc = context.getTypeConverter();
if (tc == null) {
    throw new IllegalStateException(
        "Cannot convert message body to " + type.getName()
        + " because CamelContext type converter is not available"
        + " (context not started, stopped, or not initialized)");
}
return tc.convertTo(type, this, in);
{code}

h2. Before / After

*Before:*
{noformat}
NullPointerException: Cannot invoke "TypeConverter.convertTo(...)" because the 
return value of "CamelContext.getTypeConverter()" is null
{noformat}

*After:*
{noformat}
IllegalStateException: Cannot convert message body to java.lang.String because 
CamelContext type converter is not available (context not started, stopped, or 
not initialized)
{noformat}

h2. Related

CAMEL-24510 / PR #25760 -- same fix for {{ExchangeHelper.convertToType()}} and 
{{convertToMandatoryType()}}

h2. PR

https://github.com/apache/camel/pull/25771

  was:
h2. Problem

{{AbstractExchange.getIn(Class<T>)}} and {{AbstractExchange.getOut(Class<T>)}} 
call {{context.getTypeConverter().convertTo(...)}} directly without a null 
guard. When {{CamelContext}} is shutting down, 
{{DefaultCamelContextExtension.resetTypeConverter()}} sets the type converter 
to {{null}} during {{forceStopLazyInitialization()}}. Any thread that calls 
these methods during that window gets a bare {{NullPointerException}} with no 
actionable message.

This is the same race condition as CAMEL-24510 (fixed in 
{{ExchangeHelper.convertToType}}), but affecting two additional call sites that 
bypass {{ExchangeHelper}} entirely.

h2. Root Cause

File: 
{{core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java}}

Line ~499 (getIn):
{code:java}
return context.getTypeConverter().convertTo(type, this, in);
{code}

Line ~553 (getOut):
{code:java}
return context.getTypeConverter().convertTo(type, this, out);
{code}

h2. Stack Trace

{noformat}
java.lang.NullPointerException: Cannot invoke "TypeConverter.convertTo(...)"
    because "getTypeConverter()" is null
    at 
org.apache.camel.support.AbstractExchange.getIn(AbstractExchange.java:499)
{noformat}

h2. Fix

Add null guard on the {{TypeConverter}} in both methods, throwing 
{{IllegalStateException}} with a descriptive message instead of bare NPE.

h2. Related

CAMEL-24510 — same fix for {{ExchangeHelper.convertToType()}} and 
{{convertToMandatoryType()}}


> AbstractExchange.getIn(Class) and getOut(Class) throw NPE when 
> CamelContext.getTypeConverter() is null during shutdown
> ----------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24515
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24515
>             Project: Camel
>          Issue Type: Bug
>            Reporter: mayur mohan
>            Priority: Minor
>              Labels: camel-support, diagnostic
>
> h2. Problem
> {{AbstractExchange.getIn(Class<T>)}} and 
> {{AbstractExchange.getOut(Class<T>)}} call 
> {{context.getTypeConverter().convertTo(...)}} directly without a null guard. 
> When {{CamelContext}} is shutting down, 
> {{DefaultCamelContextExtension.resetTypeConverter()}} sets the type converter 
> to {{null}} during {{forceStopLazyInitialization()}}. Any thread that calls 
> these methods during that window gets a bare {{NullPointerException}} with no 
> actionable message.
> This is the same race condition as CAMEL-24510 (fixed in 
> {{ExchangeHelper.convertToType}}), but affecting two additional call sites in 
> {{AbstractExchange}} that bypass {{ExchangeHelper}} entirely.
> h2. Root Cause
> File: 
> {{core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java}}
> Line ~499 (getIn):
> {code:java}
> return context.getTypeConverter().convertTo(type, this, in);
> {code}
> Line ~553 (getOut):
> {code:java}
> return context.getTypeConverter().convertTo(type, this, out);
> {code}
> Note: {{getOut(Class<T>)}} is called from {{getMessage(Class<T>)}} which is 
> used broadly by Camel processors and scripts.
> h2. Stack Trace
> {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. Fix
> Add null guard on the {{TypeConverter}} in both methods, throwing 
> {{IllegalStateException}} with a descriptive message instead of bare NPE:
> {code:java}
> TypeConverter tc = context.getTypeConverter();
> if (tc == null) {
>     throw new IllegalStateException(
>         "Cannot convert message body to " + type.getName()
>         + " because CamelContext type converter is not available"
>         + " (context not started, stopped, or not initialized)");
> }
> return tc.convertTo(type, this, in);
> {code}
> h2. Before / After
> *Before:*
> {noformat}
> NullPointerException: Cannot invoke "TypeConverter.convertTo(...)" because 
> the return value of "CamelContext.getTypeConverter()" is null
> {noformat}
> *After:*
> {noformat}
> IllegalStateException: Cannot convert message body to java.lang.String 
> because CamelContext type converter is not available (context not started, 
> stopped, or not initialized)
> {noformat}
> h2. Related
> CAMEL-24510 / PR #25760 -- same fix for {{ExchangeHelper.convertToType()}} 
> and {{convertToMandatoryType()}}
> h2. PR
> https://github.com/apache/camel/pull/25771



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

Reply via email to