This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-4.14.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit 079f510603a877e419e23c6c34335c2d0e704f8f Author: Claus Ibsen <[email protected]> AuthorDate: Sun Feb 8 12:35:00 2026 +0100 CAMEL-22973: camel-core - ClassCastException in Splitter with exchange pooling (#21308) --- .../camel/processor/PooledExchangeSplitTest.java | 72 ++++++++++++++++++++++ .../org/apache/camel/support/DefaultExchange.java | 6 +- .../org/apache/camel/support/MonotonicClock.java | 2 + .../org/apache/camel/support/ResetableClock.java | 4 +- 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/PooledExchangeSplitTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/PooledExchangeSplitTest.java new file mode 100644 index 000000000000..da724d73fb6e --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/processor/PooledExchangeSplitTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.processor; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.camel.CamelContext; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.impl.engine.PooledExchangeFactory; +import org.apache.camel.impl.engine.PooledProcessorExchangeFactory; +import org.junit.jupiter.api.Test; + +class PooledExchangeSplitTest extends ContextTestSupport { + + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext camelContext = super.createCamelContext(); + ExtendedCamelContext ecc = camelContext.getCamelContextExtension(); + + ecc.setExchangeFactory(new PooledExchangeFactory()); + + ecc.setProcessorExchangeFactory(new PooledProcessorExchangeFactory()); + ecc.getExchangeFactory().setStatisticsEnabled(true); + ecc.getProcessorExchangeFactory().setStatisticsEnabled(true); + + return camelContext; + } + + @Test + public void testSplitter() throws Exception { + List<Integer> data = new ArrayList<>(Arrays.asList(1, 2, 3)); + + getMockEndpoint("mock:result").expectedMessageCount(3); + + template.sendBody("direct:processData", data); + + MockEndpoint.assertIsSatisfied(context); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:processData") + .split(body()).streaming().parallelProcessing() + .to("mock:result"); + } + }; + } + +} diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java index cb4d4728fc34..c232ae712e02 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java @@ -36,17 +36,17 @@ public final class DefaultExchange extends AbstractExchange { DefaultExchange(CamelContext context, EnumMap<ExchangePropertyKey, Object> internalProperties, Map<String, Object> properties) { super(context, internalProperties, properties); - this.timeInfo = new MonotonicClock(); + this.timeInfo = new ResetableClock(); } public DefaultExchange(CamelContext context) { super(context); - this.timeInfo = new MonotonicClock(); + this.timeInfo = new ResetableClock(); } public DefaultExchange(CamelContext context, ExchangePattern pattern) { super(context, pattern); - this.timeInfo = new MonotonicClock(); + this.timeInfo = new ResetableClock(); } public DefaultExchange(Exchange parent) { diff --git a/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java b/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java index 46ab3772368c..01ab4f8beb89 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java @@ -22,6 +22,8 @@ import org.apache.camel.clock.Clock; /** * A clock that increases monotonically (i.e.: does not go back in time) for precise elapsed calculations. + * + * @see ResetableClock */ public final class MonotonicClock implements Clock { private final long created; diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ResetableClock.java b/core/camel-support/src/main/java/org/apache/camel/support/ResetableClock.java index 00091ac8353c..c9b5609aa4d1 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/ResetableClock.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/ResetableClock.java @@ -21,7 +21,9 @@ import java.util.concurrent.TimeUnit; import org.apache.camel.clock.Clock; /** - * A clock that can be reset. + * A clock for precises elapsed calculations, that also can be reset. + * + * @see MonotonicClock */ public final class ResetableClock implements Clock { private long created;
