This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new f633c6fcbcd CAMEL-21728: Loop EIP to have onPrepare processor (#17081)
f633c6fcbcd is described below
commit f633c6fcbcdfe63ad4fc3f4d051c6a379fdd1c24
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Feb 6 10:22:40 2025 +0100
CAMEL-21728: Loop EIP to have onPrepare processor (#17081)
* CAMEL-21728: Loop EIP to have onPrepare processor
---
.../org/apache/camel/catalog/models/loop.json | 3 +-
.../apache/camel/catalog/schemas/camel-spring.xsd | 10 ++++
.../META-INF/org/apache/camel/model/loop.json | 3 +-
.../org/apache/camel/model/LoopDefinition.java | 46 ++++++++++++++++
.../org/apache/camel/processor/LoopProcessor.java | 18 +++++--
.../java/org/apache/camel/reifier/LoopReifier.java | 6 ++-
.../apache/camel/processor/LoopOnPrepareTest.java | 62 ++++++++++++++++++++++
.../api/management/mbean/ManagedLoopMBean.java | 3 ++
.../apache/camel/management/mbean/ManagedLoop.java | 5 ++
.../java/org/apache/camel/xml/in/ModelParser.java | 1 +
.../java/org/apache/camel/xml/out/ModelWriter.java | 1 +
.../org/apache/camel/yaml/out/ModelWriter.java | 1 +
.../dsl/yaml/deserializers/ModelDeserializers.java | 6 +++
.../generated/resources/schema/camelYamlDsl.json | 5 ++
14 files changed, 163 insertions(+), 7 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/loop.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/loop.json
index 78bf0db166d..f89a70df2de 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/loop.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/loop.json
@@ -19,7 +19,8 @@
"copy": { "index": 4, "kind": "attribute", "displayName": "Copy", "group":
"advanced", "label": "advanced", "required": false, "type": "boolean",
"javaType": "java.lang.Boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "description": "If the copy attribute
is true, a copy of the input Exchange is used for each iteration. That means
each iteration will start from a copy of the same message. By default loop will
loop the same exchange all over, [...]
"doWhile": { "index": 5, "kind": "attribute", "displayName": "Do While",
"group": "advanced", "label": "advanced", "required": false, "type": "boolean",
"javaType": "java.lang.Boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "description": "Enables the while loop
that loops until the predicate evaluates to false or null." },
"breakOnShutdown": { "index": 6, "kind": "attribute", "displayName":
"Break On Shutdown", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false, "description": "If
the breakOnShutdown attribute is true, then the loop will not iterate until it
reaches the end when Camel is shut down." },
- "outputs": { "index": 7, "kind": "element", "displayName": "Outputs",
"group": "common", "required": true, "type": "array", "javaType":
"java.util.List<org.apache.camel.model.ProcessorDefinition<java.lang.Object>>",
"oneOf": [ "aggregate", "bean", "choice", "circuitBreaker", "claimCheck",
"convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay", "doCatch",
"doFinally", "doTry", "dynamicRouter", "enrich", "filter",
"idempotentConsumer", "intercept", "interceptFrom", "intercept [...]
+ "onPrepare": { "index": 7, "kind": "attribute", "displayName": "On
Prepare", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "org.apache.camel.Processor", "deprecated": false,
"autowired": false, "secret": false, "description": "Uses the Processor when
preparing the org.apache.camel.Exchange for each loop iteration. This can be
used to deep-clone messages, or any custom logic needed before the looping
executes." },
+ "outputs": { "index": 8, "kind": "element", "displayName": "Outputs",
"group": "common", "required": true, "type": "array", "javaType":
"java.util.List<org.apache.camel.model.ProcessorDefinition<java.lang.Object>>",
"oneOf": [ "aggregate", "bean", "choice", "circuitBreaker", "claimCheck",
"convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay", "doCatch",
"doFinally", "doTry", "dynamicRouter", "enrich", "filter",
"idempotentConsumer", "intercept", "interceptFrom", "intercept [...]
},
"exchangeProperties": {
"CamelLoopIndex": { "index": 0, "kind": "exchangeProperty", "displayName":
"Loop Index", "label": "producer", "required": false, "javaType": "int",
"deprecated": false, "autowired": false, "secret": false, "description": "Index
of the current iteration (0 based)." },
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 40197d0c90d..06008c197e7 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -7438,6 +7438,16 @@ Enables the while loop that loops until the predicate
evaluates to false or null
<![CDATA[
If the breakOnShutdown attribute is true, then the loop will not iterate until
it reaches the end when Camel is shut
down. Default value: false
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="onPrepare" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+Uses the Processor when preparing the org.apache.camel.Exchange for each loop
iteration. This can be used to deep-clone
+messages, or any custom logic needed before the looping executes.
]]>
</xs:documentation>
</xs:annotation>
diff --git
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/loop.json
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/loop.json
index 78bf0db166d..f89a70df2de 100644
---
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/loop.json
+++
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/loop.json
@@ -19,7 +19,8 @@
"copy": { "index": 4, "kind": "attribute", "displayName": "Copy", "group":
"advanced", "label": "advanced", "required": false, "type": "boolean",
"javaType": "java.lang.Boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "description": "If the copy attribute
is true, a copy of the input Exchange is used for each iteration. That means
each iteration will start from a copy of the same message. By default loop will
loop the same exchange all over, [...]
"doWhile": { "index": 5, "kind": "attribute", "displayName": "Do While",
"group": "advanced", "label": "advanced", "required": false, "type": "boolean",
"javaType": "java.lang.Boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "description": "Enables the while loop
that loops until the predicate evaluates to false or null." },
"breakOnShutdown": { "index": 6, "kind": "attribute", "displayName":
"Break On Shutdown", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false, "description": "If
the breakOnShutdown attribute is true, then the loop will not iterate until it
reaches the end when Camel is shut down." },
- "outputs": { "index": 7, "kind": "element", "displayName": "Outputs",
"group": "common", "required": true, "type": "array", "javaType":
"java.util.List<org.apache.camel.model.ProcessorDefinition<java.lang.Object>>",
"oneOf": [ "aggregate", "bean", "choice", "circuitBreaker", "claimCheck",
"convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay", "doCatch",
"doFinally", "doTry", "dynamicRouter", "enrich", "filter",
"idempotentConsumer", "intercept", "interceptFrom", "intercept [...]
+ "onPrepare": { "index": 7, "kind": "attribute", "displayName": "On
Prepare", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "org.apache.camel.Processor", "deprecated": false,
"autowired": false, "secret": false, "description": "Uses the Processor when
preparing the org.apache.camel.Exchange for each loop iteration. This can be
used to deep-clone messages, or any custom logic needed before the looping
executes." },
+ "outputs": { "index": 8, "kind": "element", "displayName": "Outputs",
"group": "common", "required": true, "type": "array", "javaType":
"java.util.List<org.apache.camel.model.ProcessorDefinition<java.lang.Object>>",
"oneOf": [ "aggregate", "bean", "choice", "circuitBreaker", "claimCheck",
"convertBodyTo", "convertHeaderTo", "convertVariableTo", "delay", "doCatch",
"doFinally", "doTry", "dynamicRouter", "enrich", "filter",
"idempotentConsumer", "intercept", "interceptFrom", "intercept [...]
},
"exchangeProperties": {
"CamelLoopIndex": { "index": 0, "kind": "exchangeProperty", "displayName":
"Loop Index", "label": "producer", "required": false, "javaType": "int",
"deprecated": false, "autowired": false, "secret": false, "description": "Index
of the current iteration (0 based)." },
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/LoopDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/LoopDefinition.java
index 8877314e31b..30d0f3f5428 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/LoopDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/LoopDefinition.java
@@ -20,9 +20,11 @@ import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlTransient;
import org.apache.camel.Expression;
import org.apache.camel.Predicate;
+import org.apache.camel.Processor;
import org.apache.camel.model.language.ExpressionDefinition;
import org.apache.camel.spi.Metadata;
@@ -34,6 +36,9 @@ import org.apache.camel.spi.Metadata;
@XmlAccessorType(XmlAccessType.FIELD)
public class LoopDefinition extends OutputExpressionNode {
+ @XmlTransient
+ private Processor onPrepareProcessor;
+
@XmlAttribute
@Metadata(label = "advanced", javaType = "java.lang.Boolean")
private String copy;
@@ -43,6 +48,9 @@ public class LoopDefinition extends OutputExpressionNode {
@XmlAttribute
@Metadata(label = "advanced", javaType = "java.lang.Boolean")
private String breakOnShutdown;
+ @XmlAttribute
+ @Metadata(label = "advanced", javaType = "org.apache.camel.Processor")
+ private String onPrepare;
public LoopDefinition() {
}
@@ -52,6 +60,8 @@ public class LoopDefinition extends OutputExpressionNode {
this.copy = source.copy;
this.doWhile = source.doWhile;
this.breakOnShutdown = source.breakOnShutdown;
+ this.onPrepareProcessor = source.onPrepareProcessor;
+ this.onPrepare = source.onPrepare;
}
public LoopDefinition(Expression expression) {
@@ -72,6 +82,10 @@ public class LoopDefinition extends OutputExpressionNode {
return new LoopDefinition(this);
}
+ public Processor getOnPrepareProcessor() {
+ return onPrepareProcessor;
+ }
+
/**
* Enables copy mode so a copy of the input Exchange is used for each
iteration.
*/
@@ -80,6 +94,30 @@ public class LoopDefinition extends OutputExpressionNode {
return this;
}
+ /**
+ * Uses the {@link Processor} when preparing the {@link
org.apache.camel.Exchange} for each loop iteration. This can
+ * be used to deep-clone messages, or any custom logic needed before the
looping executes.
+ *
+ * @param onPrepare reference to the processor to lookup in the {@link
org.apache.camel.spi.Registry}
+ * @return the builder
+ */
+ public LoopDefinition onPrepare(Processor onPrepare) {
+ this.onPrepareProcessor = onPrepare;
+ return this;
+ }
+
+ /**
+ * Uses the {@link Processor} when preparing the {@link
org.apache.camel.Exchange} for each loop iteration. This can
+ * be used to deep-clone messages, or any custom logic needed before the
looping executes.
+ *
+ * @param onPrepare reference to the processor to lookup in the {@link
org.apache.camel.spi.Registry}
+ * @return the builder
+ */
+ public LoopDefinition onPrepare(String onPrepare) {
+ setOnPrepare(onPrepare);
+ return this;
+ }
+
public String getCopy() {
return copy;
}
@@ -122,6 +160,14 @@ public class LoopDefinition extends OutputExpressionNode {
return breakOnShutdown;
}
+ public String getOnPrepare() {
+ return onPrepare;
+ }
+
+ public void setOnPrepare(String onPrepare) {
+ this.onPrepare = onPrepare;
+ }
+
@Override
public String toString() {
return "Loop[" + getExpression() + " -> " + getOutputs() + "]";
diff --git
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/LoopProcessor.java
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/LoopProcessor.java
index e4e659a6026..bf203e940c2 100644
---
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/LoopProcessor.java
+++
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/LoopProcessor.java
@@ -52,16 +52,18 @@ public class LoopProcessor extends DelegateAsyncProcessor
implements Traceable,
private final ReactiveExecutor reactiveExecutor;
private final Expression expression;
private final Predicate predicate;
+ private final Processor onPrepare;
private final boolean copy;
private final boolean breakOnShutdown;
private final LongAdder taskCount = new LongAdder();
public LoopProcessor(CamelContext camelContext, Processor processor,
Expression expression, Predicate predicate,
- boolean copy, boolean breakOnShutdown) {
+ Processor onPrepare, boolean copy, boolean
breakOnShutdown) {
super(processor);
this.reactiveExecutor =
camelContext.getCamelContextExtension().getReactiveExecutor();
this.expression = expression;
this.predicate = predicate;
+ this.onPrepare = onPrepare;
this.copy = copy;
this.breakOnShutdown = breakOnShutdown;
}
@@ -202,15 +204,19 @@ public class LoopProcessor extends DelegateAsyncProcessor
implements Traceable,
* @param index the index of the next iteration
* @return the exchange to use
*/
- protected Exchange prepareExchange(Exchange exchange, int index) {
+ protected Exchange prepareExchange(Exchange exchange, int index) throws
Exception {
+ Exchange answer = exchange;
if (copy) {
// use a copy but let it reuse the same exchange id so it appear
as one exchange
// use the original exchange rather than the looping exchange
(esp. with the async routing engine)
- return ExchangeHelper.createCopy(exchange, true);
+ answer = ExchangeHelper.createCopy(exchange, true);
} else {
ExchangeHelper.prepareOutToIn(exchange);
- return exchange;
}
+ if (onPrepare != null) {
+ onPrepare.process(answer);
+ }
+ return answer;
}
public Expression getExpression() {
@@ -225,6 +231,10 @@ public class LoopProcessor extends DelegateAsyncProcessor
implements Traceable,
return copy;
}
+ public boolean isBreakOnShutdown() {
+ return breakOnShutdown;
+ }
+
@Override
public String getTraceLabel() {
if (predicate != null) {
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/LoopReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/LoopReifier.java
index bcdc7313a92..6483c495713 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/LoopReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/LoopReifier.java
@@ -36,6 +36,10 @@ public class LoopReifier extends
ExpressionReifier<LoopDefinition> {
boolean isCopy = parseBoolean(definition.getCopy(), false);
boolean isWhile = parseBoolean(definition.getDoWhile(), false);
boolean isBreakOnShutdown =
parseBoolean(definition.getBreakOnShutdown(), false);
+ Processor prepare = definition.getOnPrepareProcessor();
+ if (prepare == null && definition.getOnPrepare() != null) {
+ prepare = mandatoryLookup(definition.getOnPrepare(),
Processor.class);
+ }
Predicate predicate = null;
Expression expression = null;
@@ -44,7 +48,7 @@ public class LoopReifier extends
ExpressionReifier<LoopDefinition> {
} else {
expression = createExpression(definition.getExpression());
}
- return new LoopProcessor(camelContext, output, expression, predicate,
isCopy, isBreakOnShutdown);
+ return new LoopProcessor(camelContext, output, expression, predicate,
prepare, isCopy, isBreakOnShutdown);
}
}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/processor/LoopOnPrepareTest.java
b/core/camel-core/src/test/java/org/apache/camel/processor/LoopOnPrepareTest.java
new file mode 100644
index 00000000000..88e236e8093
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/processor/LoopOnPrepareTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+public class LoopOnPrepareTest extends ContextTestSupport {
+
+ @Test
+ public void testLoopOnPrepare() throws Exception {
+ getMockEndpoint("mock:loop").expectedBodiesReceived("AB", "AB", "AB");
+ getMockEndpoint("mock:result").expectedBodiesReceived("AB");
+
+ template.sendBody("direct:start", "A");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .loop(3).onPrepare(new
MyPrepare()).transform(body().append("B")).to("mock:loop").end().to("mock:result");
+ }
+ };
+ }
+
+ private class MyPrepare implements Processor {
+
+ private String original;
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ if (original == null) {
+ original = exchange.getMessage().getBody(String.class);
+ } else {
+ // restore original input for each loop
+ exchange.getMessage().setBody(original);
+ }
+ }
+ }
+}
diff --git
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedLoopMBean.java
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedLoopMBean.java
index a75551f4f3b..140cf4032ac 100644
---
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedLoopMBean.java
+++
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedLoopMBean.java
@@ -29,4 +29,7 @@ public interface ManagedLoopMBean extends
ManagedProcessorMBean {
@ManagedAttribute(description = "Whether a copy of the input Exchange is
used for each iteration")
Boolean isCopy();
+ @ManagedAttribute(description = "Whether to break looping if Camel is
being shutdown")
+ Boolean isBreakOnShutdown();
+
}
diff --git
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedLoop.java
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedLoop.java
index 1bf0270e197..eb2dea9b7e7 100644
---
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedLoop.java
+++
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedLoop.java
@@ -50,4 +50,9 @@ public class ManagedLoop extends ManagedProcessor implements
ManagedLoopMBean {
public Boolean isCopy() {
return processor.isCopy();
}
+
+ @Override
+ public Boolean isBreakOnShutdown() {
+ return processor.isBreakOnShutdown();
+ }
}
diff --git
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 46fa4335bdd..e0aa413639d 100644
---
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -531,6 +531,7 @@ public class ModelParser extends BaseParser {
case "breakOnShutdown": def.setBreakOnShutdown(val); yield
true;
case "copy": def.setCopy(val); yield true;
case "doWhile": def.setDoWhile(val); yield true;
+ case "onPrepare": def.setOnPrepare(val); yield true;
default: yield
processorDefinitionAttributeHandler().accept(def, key, val);
}, outputExpressionNodeElementHandler(), noValueHandler());
}
diff --git
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index e185a32151c..08d86619ceb 100644
---
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -1163,6 +1163,7 @@ public class ModelWriter extends BaseWriter {
protected void doWriteLoopDefinition(String name, LoopDefinition def)
throws IOException {
startElement(name);
doWriteProcessorDefinitionAttributes(def);
+ doWriteAttribute("onPrepare", def.getOnPrepare(), null);
doWriteAttribute("doWhile", def.getDoWhile(), null);
doWriteAttribute("breakOnShutdown", def.getBreakOnShutdown(), null);
doWriteAttribute("copy", def.getCopy(), null);
diff --git
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index d9d911932fa..5175a869386 100644
---
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -1163,6 +1163,7 @@ public class ModelWriter extends BaseWriter {
protected void doWriteLoopDefinition(String name, LoopDefinition def)
throws IOException {
startElement(name);
doWriteProcessorDefinitionAttributes(def);
+ doWriteAttribute("onPrepare", def.getOnPrepare(), null);
doWriteAttribute("doWhile", def.getDoWhile(), null);
doWriteAttribute("breakOnShutdown", def.getBreakOnShutdown(), null);
doWriteAttribute("copy", def.getCopy(), null);
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index aefab1977f5..5fbdc56df6f 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -9545,6 +9545,7 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
@YamlProperty(name = "doWhile", type = "boolean",
description = "Enables the while loop that loops until the predicate evaluates
to false or null.", displayName = "Do While"),
@YamlProperty(name = "expression", type =
"object:org.apache.camel.model.language.ExpressionDefinition", description =
"Expression to define how many times we should loop. Notice the expression is
only evaluated once, and should return a number as how many times to loop. A
value of zero or negative means no looping. The loop is like a for-loop
fashion, if you want a while loop, then the dynamic router may be a better
choice.", displayName = "Expression", oneOf = "expr [...]
@YamlProperty(name = "id", type = "string", description =
"Sets the id of this node", displayName = "Id"),
+ @YamlProperty(name = "onPrepare", type = "string",
description = "Uses the Processor when preparing the org.apache.camel.Exchange
for each loop iteration. This can be used to deep-clone messages, or any custom
logic needed before the looping executes.", displayName = "On Prepare"),
@YamlProperty(name = "steps", type =
"array:org.apache.camel.model.ProcessorDefinition")
}
)
@@ -9588,6 +9589,11 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
target.setExpression(val);
break;
}
+ case "onPrepare": {
+ String val = asText(node);
+ target.setOnPrepare(val);
+ break;
+ }
case "id": {
String val = asText(node);
target.setId(val);
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index 514a3be0ef1..7deecd56aaf 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -2775,6 +2775,11 @@
"title" : "Id",
"description" : "Sets the id of this node"
},
+ "onPrepare" : {
+ "type" : "string",
+ "title" : "On Prepare",
+ "description" : "Uses the Processor when preparing the
org.apache.camel.Exchange for each loop iteration. This can be used to
deep-clone messages, or any custom logic needed before the looping executes."
+ },
"steps" : {
"type" : "array",
"items" : {