Hi All,
I’m seeing a NullPointerException in Camel 4.18.0 when using the pooled
exchange together with a splitter EIP in a Spring Boot application. The
warning indicates the exception is ignored, but it may point to an
underlying issue. Please let me know if I have missed anything.
*Log:*
2026-02-19T22:03:22.518-06:00 WARN 85713 --- [ main]
o.apache.camel.support.UnitOfWorkHelper : Exception occurred during done
UnitOfWork for Exchange: 0AE40C170596909-0000000000000000. This exception
will be ignored.
*java.lang.NullPointerException: Cannot invoke
"org.apache.camel.Exchange.getExchangeExtension()" because "this.exchange"
is null*
at
org.apache.camel.impl.engine.DefaultUnitOfWork.onDone(DefaultUnitOfWork.java:310)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultUnitOfWork.done(DefaultUnitOfWork.java:303)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.support.UnitOfWorkHelper.doneUow(UnitOfWorkHelper.java:53)
~[camel-support-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:1177)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:1114)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.AdviceIterator.runAfterTask(AdviceIterator.java:45)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.SharedCamelInternalProcessor$InternalCallback.done(SharedCamelInternalProcessor.java:224)
~[camel-base-engine-4.18.0.jar:4.18.0]
at org.apache.camel.AsyncCallback.run(AsyncCallback.java:44)
~[camel-api-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.doRun(DefaultReactiveExecutor.java:199)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.executeReactiveWork(DefaultReactiveExecutor.java:189)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.tryExecuteReactiveWork(DefaultReactiveExecutor.java:166)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59)
~[camel-base-engine-4.18.0.jar:4.18.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:162)
~[camel-core-processor-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.CamelInternalProcessor.processNonTransacted(CamelInternalProcessor.java:385)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:361)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:102)
~[camel-direct-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.SharedCamelInternalProcessor.processNonTransacted(SharedCamelInternalProcessor.java:156)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.SharedCamelInternalProcessor.process(SharedCamelInternalProcessor.java:133)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.SharedCamelInternalProcessor$1.process(SharedCamelInternalProcessor.java:89)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:81)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.SharedCamelInternalProcessor.process(SharedCamelInternalProcessor.java:86)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.support.cache.DefaultProducerCache.send(DefaultProducerCache.java:180)
~[camel-support-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultProducerTemplate.send(DefaultProducerTemplate.java:175)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultProducerTemplate.send(DefaultProducerTemplate.java:171)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultProducerTemplate.send(DefaultProducerTemplate.java:152)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:186)
~[camel-base-engine-4.18.0.jar:4.18.0]
at
org.apache.camel.impl.engine.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:194)
~[camel-base-engine-4.18.0.jar:4.18.0]
*Test Code*
package com.example.camel;
import org.apache.camel.*;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@CamelSpringBootTest
@EnableAutoConfiguration
@SpringBootTest(
properties = {"camel.main.exchange-factory=pooled"}
)
public class PooledExchangeSplitterSpringTest {
@EndpointInject("mock:result")
MockEndpoint mockEndpoint;
@Autowired
ProducerTemplate producerTemplate;
@Configuration
static class TestConfig {
@Bean
RoutesBuilder route() {
return new RouteBuilder() {
@Override
public void configure() {
from("direct:processData")
.split(body())
.to("mock:result");
}
};
}
}
@Test
public void testSplitter() throws InterruptedException {
List<Integer> data = new ArrayList<>();
int total = 3;
for (int i = 0; i < total; i++) {
data.add(i);
}
mockEndpoint.setExpectedMessageCount(total);
producerTemplate.sendBody("direct:processData", data);
mockEndpoint.assertIsSatisfied();
}
}
Camel Version: 4.18.0
Spring Boot Version: 3.5.10
Java Version: 17
I expect no NPE when UnitOfWork completes.
Thanks,
DK