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

Reply via email to