This is an automated email from the ASF dual-hosted git repository.
Croway 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 0df36802514c CAMEL-25494: camel-yaml-io - write the onException,
onCompletion and interceptors of a route configuration as the YAML DSL loads
them (#27629)
0df36802514c is described below
commit 0df36802514c255c7ab2a0f9df37ee6c16b72fd0
Author: Federico Mariani <[email protected]>
AuthorDate: Sun Oct 11 10:11:29 2026 +0200
CAMEL-25494: camel-yaml-io - write the onException, onCompletion and
interceptors of a route configuration as the YAML DSL loads them (#27629)
* CAMEL-25494: camel-yaml-io - write the onException, onCompletion and
interceptors of a route configuration as the YAML DSL loads them
Each item of these lists is written as a one-key map (- onException: ...),
as the YAML DSL reads them
(wrapItem = true in RouteConfigurationDefinitionDeserializer). The uri of
interceptFrom and
interceptSendToEndpoint is a pattern and is no longer split into
parameters, which their YAML DSL schema
does not have.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* CAMEL-25494: trim the writer test to the items it already covered, the
round trip test covers the others
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../org/apache/camel/yaml/out/YamlModelWriter.java | 10 +--
.../org/apache/camel/yaml/LwModelToYAMLDumper.java | 22 ++++++
.../camel/yaml/out/YamlModelWriterSupport.java | 19 +++++
.../src/test/resources/yaml-routeconfig.yaml | 24 ++++---
.../dsl/yaml/RouteConfigurationYamlDumpTest.java | 83 ++++++++++++++++++++++
.../main/resources/velocity/model-yaml-writer.vm | 5 ++
6 files changed, 147 insertions(+), 16 deletions(-)
diff --git
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
index 195c4ebaaa0c..85612baebdc6 100644
---
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
+++
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
@@ -1614,11 +1614,11 @@ public class YamlModelWriter extends
YamlModelWriterSupport {
JsonObject jo = new JsonObject();
doWriteOptionalIdentifiedDefinitionAttributes(jo, def);
doWriteAttribute(jo, "precondition", def.getPrecondition(), null);
- doWriteChildList(jo, null, "onException", def.getOnExceptions(),
this::doWriteOnExceptionDefinition);
- doWriteChildList(jo, null, "onCompletion", def.getOnCompletions(),
this::doWriteOnCompletionDefinition);
- doWriteChildList(jo, null, "interceptSendToEndpoint",
def.getInterceptSendTos(), this::doWriteInterceptSendToEndpointDefinition);
- doWriteChildList(jo, null, "interceptFrom", def.getInterceptFroms(),
this::doWriteInterceptFromDefinition);
- doWriteChildList(jo, null, "intercept", def.getIntercepts(),
this::doWriteInterceptDefinition);
+ doWriteWrappedChildList(jo, "onException", def.getOnExceptions(),
this::doWriteOnExceptionDefinition);
+ doWriteWrappedChildList(jo, "onCompletion", def.getOnCompletions(),
this::doWriteOnCompletionDefinition);
+ doWriteWrappedChildList(jo, "interceptSendToEndpoint",
def.getInterceptSendTos(), this::doWriteInterceptSendToEndpointDefinition);
+ doWriteWrappedChildList(jo, "interceptFrom", def.getInterceptFroms(),
this::doWriteInterceptFromDefinition);
+ doWriteWrappedChildList(jo, "intercept", def.getIntercepts(),
this::doWriteInterceptDefinition);
doWriteChildElement(jo, "errorHandler", def.getErrorHandler(),
this::doWriteErrorHandlerDefinition);
return jo;
}
diff --git
a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
index 22510f4548b7..31424f5136e2 100644
---
a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
+++
b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
@@ -36,6 +36,8 @@ import org.apache.camel.model.BeanFactoryDefinition;
import org.apache.camel.model.DataFormatDefinition;
import org.apache.camel.model.ExpressionNode;
import org.apache.camel.model.FromDefinition;
+import org.apache.camel.model.InterceptFromDefinition;
+import org.apache.camel.model.InterceptSendToEndpointDefinition;
import org.apache.camel.model.OptionalIdentifiedDefinition;
import org.apache.camel.model.RouteConfigurationDefinition;
import org.apache.camel.model.RouteConfigurationsDefinition;
@@ -137,6 +139,26 @@ public class LwModelToYAMLDumper implements
ModelToYAMLDumper {
super.doWriteAttribute(jo, key, value, defaultValue);
}
+ @Override
+ protected JsonObject
doWriteInterceptFromDefinition(InterceptFromDefinition def) {
+ return
keepUriPattern(super.doWriteInterceptFromDefinition(def), def.getUri());
+ }
+
+ @Override
+ protected JsonObject
doWriteInterceptSendToEndpointDefinition(InterceptSendToEndpointDefinition def)
{
+ return
keepUriPattern(super.doWriteInterceptSendToEndpointDefinition(def),
def.getUri());
+ }
+
+ // the uri of an interceptor is a pattern (such as mock:*), not an
endpoint uri, and the YAML DSL has no
+ // parameters for it, so it is written as it is even when the uris
are written as parameters
+ private JsonObject keepUriPattern(JsonObject jo, String uri) {
+ if (uriAsParameters && uri != null) {
+ jo.remove("parameters");
+ jo.put("uri", resolvePlaceholders ? resolve(uri,
properties) : uri);
+ }
+ return jo;
+ }
+
@Override
protected JsonObject
doWriteThrowExceptionDefinition(ThrowExceptionDefinition def) {
JsonObject jo = super.doWriteThrowExceptionDefinition(def);
diff --git
a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/out/YamlModelWriterSupport.java
b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/out/YamlModelWriterSupport.java
index 7afb70b04074..a83ac7310f3e 100644
---
a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/out/YamlModelWriterSupport.java
+++
b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/out/YamlModelWriterSupport.java
@@ -196,6 +196,25 @@ public abstract class YamlModelWriterSupport {
}
}
+ /**
+ * A list whose items the YAML DSL reads as one-key maps named after the
list, such as the onException of a route
+ * configuration: <code>onException: [ { onException: { ... } } ]</code>
+ */
+ protected <T> void doWriteWrappedChildList(JsonObject jo, String key,
List<T> list, Function<T, JsonObject> writer) {
+ if (list != null && !list.isEmpty()) {
+ JsonArray arr = new JsonArray();
+ for (T item : list) {
+ JsonObject child = writer.apply(item);
+ if (child != null) {
+ arr.add(wrapNode(key, child));
+ }
+ }
+ if (!arr.isEmpty()) {
+ jo.put(key, arr);
+ }
+ }
+ }
+
protected JsonObject wrapNode(String key, JsonObject value) {
JsonObject wrapper = new JsonObject();
if (value != null) {
diff --git a/core/camel-yaml-io/src/test/resources/yaml-routeconfig.yaml
b/core/camel-yaml-io/src/test/resources/yaml-routeconfig.yaml
index daeb77d2ddc2..f7bfd73f89b2 100644
--- a/core/camel-yaml-io/src/test/resources/yaml-routeconfig.yaml
+++ b/core/camel-yaml-io/src/test/resources/yaml-routeconfig.yaml
@@ -19,15 +19,17 @@
customId: true
id: myConfig
onException:
- - exception:
- - java.lang.Exception
- handled:
- constant:
- expression: "true"
- steps:
- - to:
- uri: mock:error
+ - onException:
+ exception:
+ - java.lang.Exception
+ handled:
+ constant:
+ expression: "true"
+ steps:
+ - to:
+ uri: mock:error
intercept:
- - steps:
- - log:
- message: intercepted
+ - intercept:
+ steps:
+ - log:
+ message: intercepted
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/dsl/yaml/RouteConfigurationYamlDumpTest.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/dsl/yaml/RouteConfigurationYamlDumpTest.java
new file mode 100644
index 000000000000..0c3728720802
--- /dev/null
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/dsl/yaml/RouteConfigurationYamlDumpTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.dsl.yaml;
+
+import org.apache.camel.dsl.yaml.support.YamlTestSupport;
+import org.apache.camel.model.Model;
+import org.apache.camel.model.RouteConfigurationDefinition;
+import org.apache.camel.model.RouteConfigurationsDefinition;
+import org.apache.camel.yaml.LwModelToYAMLDumper;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class RouteConfigurationYamlDumpTest extends YamlTestSupport {
+
+ @Test
+ void routeConfigurationIsDumpedAsTheYamlDslLoadsIt() throws Exception {
+ loadRoutes("""
+ - routeConfiguration:
+ id: myConfig
+ onException:
+ - onException:
+ exception:
+ - java.lang.Exception
+ handled:
+ constant: "true"
+ steps:
+ - to: mock:error
+ onCompletion:
+ - onCompletion:
+ steps:
+ - to: mock:completed
+ interceptSendToEndpoint:
+ - interceptSendToEndpoint:
+ uri: "mock:result*"
+ steps:
+ - to: mock:send
+ interceptFrom:
+ - interceptFrom:
+ uri: "direct*"
+ steps:
+ - to: mock:from
+ intercept:
+ - intercept:
+ steps:
+ - to: mock:intercept
+ """);
+ Model model =
context.getCamelContextExtension().getContextPlugin(Model.class);
+
+ // as the route configurations are dumped by camel.main.dumpRoutes,
which camel validate normalize uses
+ RouteConfigurationsDefinition configs = new
RouteConfigurationsDefinition();
+
configs.getRouteConfigurations().addAll(model.getRouteConfigurationDefinitions());
+ String yaml = new LwModelToYAMLDumper().dumpModelAsYaml(context,
configs, false, true, false, false);
+
+ // the dump is valid for the YAML DSL schema and loads with the same
content
+
model.removeRouteConfiguration(model.getRouteConfigurationDefinition("myConfig"));
+ loadRoutes(yaml);
+ RouteConfigurationDefinition config =
model.getRouteConfigurationDefinition("myConfig");
+ assertThat(config).isNotNull();
+ assertThat(config.getOnExceptions()).singleElement()
+ .satisfies(oe ->
assertThat(oe.getExceptions()).containsExactly("java.lang.Exception"));
+ assertThat(config.getOnCompletions()).hasSize(1);
+ assertThat(config.getInterceptSendTos()).singleElement()
+ .satisfies(i ->
assertThat(i.getUri()).isEqualTo("mock:result*"));
+ assertThat(config.getInterceptFroms()).singleElement()
+ .satisfies(i -> assertThat(i.getUri()).isEqualTo("direct*"));
+ assertThat(config.getIntercepts()).hasSize(1);
+ }
+}
diff --git
a/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
b/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
index ab82780d74be..8f294d11b62f 100644
---
a/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
+++
b/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
@@ -17,6 +17,9 @@
#set( $default = "#[[##default]]#" )
## the YAML DSL names some lists other than the XML DSL does (keyed by
class.member)
#set( $yamlKeys = { "VerbDefinition.params": "param",
"VerbDefinition.responseMsgs": "responseMessage",
"RouteTemplateDefinition.templateParameters": "parameters",
"RouteTemplateDefinition.templateBeans": "beans" } )
+## the YAML DSL reads each item of some lists as a one-key map named after the
list (wrapItem = true in the YAML DSL
+## deserializer), such as - onException: ... in a route configuration (keyed
by class.member)
+#set( $wrapItems = [ "RouteConfigurationDefinition.intercepts",
"RouteConfigurationDefinition.interceptFroms",
"RouteConfigurationDefinition.interceptSendTos",
"RouteConfigurationDefinition.onCompletions",
"RouteConfigurationDefinition.onExceptions" ] )
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -224,6 +227,8 @@ public class YamlModelWriter extends YamlModelWriterSupport
{
#end
#if( $t == "String" )
doWriteStringList(jo, #if($w)"${w}"#{else}null#end, "${n}",
def.${member.getter}());
+ #elseif(
$wrapItems.contains("${clazz.simpleName}.${member.name}") )
+ doWriteWrappedChildList(jo, "${n}", def.${member.getter}(),
this::doWrite${t});
#else
doWriteChildList(jo, #if($w)"${w}"#{else}null#end, "${n}",
def.${member.getter}(), this::doWrite${t});
#end