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 197e70656a41 CAMEL-25490: camel-yaml-io - dump a top-level onException
as top-level, not as a step of every route (#27609)
197e70656a41 is described below
commit 197e70656a413ec5aa9e0f8dd35fdd383e843312
Author: Federico Mariani <[email protected]>
AuthorDate: Sun Oct 11 10:30:22 2026 +0200
CAMEL-25490: camel-yaml-io - dump a top-level onException as top-level, not
as a step of every route (#27609)
* CAMEL-25490: camel-yaml-io - dump a top-level onException as top-level,
not as a step of every route
When routes are prepared, the context scoped onExceptions (the top-level
onException of a YAML file, the onException of a RouteBuilder, and those
of the route configurations that apply) are added to the outputs of each
route. The YAML dumper wrote them as steps of every route, which the YAML
DSL schema rejects, so camel validate normalize turned a valid file into
an invalid one.
The YAML dumper now leaves the context scoped onExceptions out of the
route steps, and writes those that do not belong to a route configuration
once, as top-level onException entries before the routes.
* CAMEL-25490: camel-core-engine - dump the routes of all the files
together when they go into one YAML file
When the routes are dumped into a single file (dumpRoutesOutput is a file,
as camel validate normalize does), the routes of each source file were
dumped separately and appended, so the top-level onException of a second
file came after the routes of the first file, which the YAML DSL loader
rejects. The routes of all the files are now dumped together, so every
top-level onException comes before the first route.
* CAMEL-25490: camel-yaml-io - guard against a null onException list of a
route configuration
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* CAMEL-25490: camel-core-engine - dump the routes of one file into a file
with their source, and warn when a top-level onException applies to the routes
of other files
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* CAMEL-25490: upgrade guide entries for the YAML dump of a top-level
onException
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* CAMEL-25490: trim overlapping test assertions
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../camel/impl/DefaultDumpRoutesStrategy.java | 60 ++++-
.../org/apache/camel/yaml/LwModelToYAMLDumper.java | 63 ++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_22.adoc | 12 +
.../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 11 +
.../camel/dsl/yaml/OnExceptionYamlDumpTest.java | 252 +++++++++++++++++++++
5 files changed, 396 insertions(+), 2 deletions(-)
diff --git
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
index fc7a187c317a..8a8103adf340 100644
---
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
+++
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
@@ -23,6 +23,7 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -34,6 +35,8 @@ import org.apache.camel.NamedNode;
import org.apache.camel.model.BeanFactoryDefinition;
import org.apache.camel.model.DataFormatDefinition;
import org.apache.camel.model.Model;
+import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.RouteConfigurationDefinition;
import org.apache.camel.model.RouteConfigurationsDefinition;
import org.apache.camel.model.RouteDefinition;
@@ -516,14 +519,24 @@ public class DefaultDumpRoutesStrategy extends
ServiceSupport implements DumpRou
if (include.contains("*") || include.contains("all") ||
include.contains("routes")) {
int size = model.getRouteDefinitions().size();
if (size > 0) {
- Map<Resource, RoutesDefinition> groups = new LinkedHashMap<>();
+ List<RouteDefinition> eligible = new ArrayList<>();
for (RouteDefinition route : model.getRouteDefinitions()) {
if ((route.isRest() != null && route.isRest()) ||
(route.isTemplate() != null && route.isTemplate())) {
// skip routes that are rest/templates
continue;
}
+ eligible.add(route);
+ }
+ // the routes of several resources dumped into the same file
are dumped together, so the top-level
+ // elements of the resources (such as onException) come before
the first route
+ boolean merge = outputFileName != null &&
countResources(eligible) > 1;
+ if (merge) {
+ warnIfOnExceptionScopeWidens(model, eligible);
+ }
+ Map<Resource, RoutesDefinition> groups = new LinkedHashMap<>();
+ for (RouteDefinition route : eligible) {
Resource res = route.getResource();
- if (res == null) {
+ if (res == null || merge) {
res = dummy;
}
RoutesDefinition routes = groups.computeIfAbsent(res,
resource -> new RoutesDefinition());
@@ -548,6 +561,49 @@ public class DefaultDumpRoutesStrategy extends
ServiceSupport implements DumpRou
}
+ private static int countResources(List<RouteDefinition> routes) {
+ Set<Resource> resources = new HashSet<>();
+ for (RouteDefinition route : routes) {
+ resources.add(route.getResource());
+ }
+ return resources.size();
+ }
+
+ /**
+ * A top-level onException applies only to the routes of its own resource,
but once the routes of several resources
+ * are dumped into the same file, it applies to all the routes of the file
when the file is loaded.
+ */
+ private void warnIfOnExceptionScopeWidens(Model model,
List<RouteDefinition> routes) {
+ Set<String> locations = new LinkedHashSet<>();
+ for (RouteDefinition route : routes) {
+ for (ProcessorDefinition<?> output : route.getOutputs()) {
+ if (output instanceof OnExceptionDefinition oe &&
!oe.isRouteScoped()
+ && !isInRouteConfiguration(model, oe)) {
+ Resource res = route.getResource();
+ locations.add(res != null && res.getLocation() != null ?
res.getLocation() : "routes without a source");
+ }
+ }
+ }
+ if (!locations.isEmpty()) {
+ LOG.warn("The routes of several resources are dumped together into
{}: the top-level onException of {}"
+ + " applies to all the routes of the dump when it is
loaded",
+ outputFileName, String.join(", ", locations));
+ }
+ }
+
+ private static boolean isInRouteConfiguration(Model model,
OnExceptionDefinition oe) {
+ for (RouteConfigurationDefinition config :
model.getRouteConfigurationDefinitions()) {
+ if (config.getOnExceptions() != null) {
+ for (OnExceptionDefinition o : config.getOnExceptions()) {
+ if (o == oe) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
protected void doDumpRoutesAsJava(CamelContext camelContext) {
final ModelToJavaDumper dumper =
PluginHelper.getModelToJavaDumper(camelContext);
final Model model =
camelContext.getCamelContextExtension().getContextPlugin(Model.class);
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 31424f5136e2..6d6a6441be5e 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
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.function.Consumer;
+import java.util.function.Function;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
@@ -38,6 +39,8 @@ 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.Model;
+import org.apache.camel.model.OnExceptionDefinition;
import org.apache.camel.model.OptionalIdentifiedDefinition;
import org.apache.camel.model.RouteConfigurationDefinition;
import org.apache.camel.model.RouteConfigurationsDefinition;
@@ -108,7 +111,29 @@ public class LwModelToYAMLDumper implements
ModelToYAMLDumper {
extractor.accept(route);
}
+ // context scoped onExceptions (a top-level onException in the YAML
DSL, an onException in the configure method
+ // of a RouteBuilder, or one of a route configuration) are added to
the outputs of each route when the routes
+ // are prepared, but the YAML DSL does not allow them in the steps of
a route
+ List<OnExceptionDefinition> contextScoped = new ArrayList<>();
+ if (definition instanceof RoutesDefinition routes) {
+ routes.getRoutes().forEach(route ->
collectContextScopedOnExceptions(route, contextScoped));
+ } else if (definition instanceof RouteDefinition route) {
+ collectContextScopedOnExceptions(route, contextScoped);
+ }
+ // the onExceptions of a route configuration are dumped with the route
configuration, the others are dumped
+ // once, as top-level onExceptions before the routes
+ List<OnExceptionDefinition> topLevel = new ArrayList<>(contextScoped);
+ topLevel.removeIf(oe -> isInRouteConfiguration(context, oe));
+
YamlModelWriter writer = new YamlModelWriter() {
+ @Override
+ protected <T> void doWriteOutputs(JsonObject jo, List<T> list,
Function<T, JsonObject> writer) {
+ if (list != null && !contextScoped.isEmpty()) {
+ list = list.stream().filter(o ->
!containsInstance(contextScoped, o)).toList();
+ }
+ super.doWriteOutputs(jo, list, writer);
+ }
+
@Override
protected void doWriteOptionalIdentifiedDefinitionAttributes(
JsonObject jo, OptionalIdentifiedDefinition<?> def) {
@@ -200,6 +225,9 @@ public class LwModelToYAMLDumper implements
ModelToYAMLDumper {
List<JsonObject> roots = new ArrayList<>();
try {
+ for (OnExceptionDefinition oe : topLevel) {
+ roots.add(writer.writeOnExceptionDefinition(oe));
+ }
if (definition instanceof RoutesDefinition rd) {
for (RouteDefinition route : rd.getRoutes()) {
roots.add(writer.writeRouteDefinition(route));
@@ -289,6 +317,41 @@ public class LwModelToYAMLDumper implements
ModelToYAMLDumper {
return buffer.toString();
}
+ /**
+ * Collects the context scoped onExceptions that were added to the outputs
of the route when it was prepared
+ */
+ private static void collectContextScopedOnExceptions(RouteDefinition
route, List<OnExceptionDefinition> answer) {
+ for (var output : route.getOutputs()) {
+ if (output instanceof OnExceptionDefinition oe &&
!oe.isRouteScoped() && !containsInstance(answer, oe)) {
+ answer.add(oe);
+ }
+ }
+ }
+
+ private static boolean isInRouteConfiguration(CamelContext context,
OnExceptionDefinition oe) {
+ Model model = context != null ?
context.getCamelContextExtension().getContextPlugin(Model.class) : null;
+ if (model != null) {
+ for (RouteConfigurationDefinition config :
model.getRouteConfigurationDefinitions()) {
+ if (containsInstance(config.getOnExceptions(), oe)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean containsInstance(List<?> list, Object instance) {
+ if (list == null) {
+ return false;
+ }
+ for (Object o : list) {
+ if (o == instance) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Extract all XML namespaces from the expressions in the route
*
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
index 5b8d13eebf62..13d53b9a17f2 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
@@ -20,6 +20,18 @@ counted each exchange once per member route instead of once
per entry into the g
unintended side effect of CAMEL-24590. The counters now count each exchange
once per entry into the
group again, as in 4.22.0: calls nested inside another route of the same group
are not counted again.
+=== Route dumps as YAML - top-level onException
+
+A top-level `onException` (of a YAML file, or in the `configure` method of a
`RouteBuilder`) is now dumped as YAML
+(`camel.main.dumpRoutes=yaml`, `camel validate normalize`) once as a top-level
`onException` before the routes, instead
+of as a step of every route, and the `onException` of a route configuration is
only dumped with the route
+configuration, no longer in the routes. Before, such a dump did not load in
the YAML DSL.
+
+When `camel.main.dumpRoutesOutput` is a file and the routes come from several
files, they are now dumped together, so a
+top-level `onException` comes before the first route. When the dump is loaded,
such an `onException` applies to the
+routes of all the files, not only to those of its own file, and a WARN is
logged when the routes are dumped. Dump into
+a directory to keep one file per source file.
+
=== camel-pqc - Bouncy Castle 1.86 (Breaking change)
Camel 4.22.2 uses Bouncy Castle 1.86, which removes the legacy implementations
of several post-quantum
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 943563d8329e..36733808a431 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -5211,6 +5211,17 @@ as Java, the error handler of an XML or YAML route is
now `.errorHandler(...)` o
The `timeout(long)` of the Resequencer EIP in Java keeps the millis as given
(`2000`), instead of a duration
(`2s0ms`).
+A top-level `onException` (of a YAML file, or in the `configure` method of a
`RouteBuilder`) is now dumped once as a
+top-level `onException` before the routes, instead of as a step of every
route, and the `onException` of a route
+configuration is only dumped with the route configuration, no longer in the
routes. This also applies to the dump of a
+single route (JMX `dumpRouteAsYaml`, the `route-dump` developer console).
Before, such a dump did not load in the YAML
+DSL.
+
+When `camel.main.dumpRoutesOutput` is a file and the routes come from several
files, they are now dumped together, so a
+top-level `onException` comes before the first route. When the dump is loaded,
such an `onException` applies to the
+routes of all the files, not only to those of its own file, and a WARN is
logged when the routes are dumped. Dump into
+a directory to keep one file per source file.
+
=== camel-jbang-mcp - camel_transform_route
The `camel_transform_route` tool now converts with the same route DSL
converter as `camel transform route
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/dsl/yaml/OnExceptionYamlDumpTest.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/dsl/yaml/OnExceptionYamlDumpTest.java
new file mode 100644
index 000000000000..4aae60a0d887
--- /dev/null
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/java/org/apache/camel/dsl/yaml/OnExceptionYamlDumpTest.java
@@ -0,0 +1,252 @@
+/*
+ * 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 java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.NamedNode;
+import org.apache.camel.dsl.yaml.support.YamlTestSupport;
+import org.apache.camel.impl.DefaultDumpRoutesStrategy;
+import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.spi.ModelToYAMLDumper;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.yaml.LwModelToYAMLDumper;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.Property;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class OnExceptionYamlDumpTest extends YamlTestSupport {
+
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ void topLevelOnExceptionIsDumpedAsTopLevel(boolean started) throws
Exception {
+ loadRoutes("""
+ - onException:
+ exception:
+ - java.lang.Exception
+ handled:
+ constant:
+ expression: "true"
+ steps:
+ - to: mock:error
+ - route:
+ id: first
+ from:
+ uri: direct:first
+ steps:
+ - to: mock:first
+ - route:
+ id: second
+ from:
+ uri: direct:second
+ steps:
+ - to: mock:second
+ """);
+ if (started) {
+ context.start();
+ }
+ String yaml = dumpRoutes();
+ // a route dumped alone (JMX dumpRouteAsYaml, the route-dump dev
console)
+ String single = new LwModelToYAMLDumper()
+ .dumpModelAsYaml(context, context.getRouteDefinition("first"),
false, true, false, false);
+ if (started) {
+ context.stop();
+ }
+
+ // written once, before the routes, and not in the steps of each route
+ assertThat(yaml).startsWith("- onException:");
+ assertThat(yaml.split("onException:", -1)).hasSize(2);
+ // also before a route dumped alone
+ assertThat(single).startsWith("- onException:").contains("id:
first").doesNotContain("id: second");
+
+ // the dump is valid for the YAML DSL schema, and the onException
still applies to all the routes
+
context.removeRouteDefinitions(List.copyOf(context.getRouteDefinitions()));
+ loadRoutes(yaml);
+ for (String id : List.of("first", "second")) {
+ OnExceptionDefinition oe = (OnExceptionDefinition)
context.getRouteDefinition(id).getOutputs().get(0);
+ assertThat(oe.isRouteScoped()).isFalse();
+
assertThat(oe.getExceptions()).containsExactly("java.lang.Exception");
+ }
+ }
+
+ @Test
+ void routeConfigurationOnExceptionIsNotDumpedInTheRoutes() throws
Exception {
+ loadRoutes("""
+ - routeConfiguration:
+ onException:
+ - onException:
+ exception:
+ - java.lang.Exception
+ handled:
+ constant:
+ expression: "true"
+ steps:
+ - to: mock:error
+ """);
+ loadRoutes("""
+ - route:
+ id: myRoute
+ from:
+ uri: direct:start
+ steps:
+ - to: mock:result
+ """);
+
assertThat(context.getRouteDefinition("myRoute").getOutputs().get(0)).isInstanceOf(OnExceptionDefinition.class);
+
+ // the onException is dumped with the route configuration
+ String yaml = dumpRoutes();
+ assertThat(yaml).doesNotContain("onException").contains("id: myRoute");
+ context.removeRouteDefinition(context.getRouteDefinition("myRoute"));
+ loadRoutes(yaml);
+ }
+
+ @Test
+ void onExceptionOfAnotherFileIsDumpedBeforeTheRoutesInOneFile(@TempDir
Path dir) throws Exception {
+ // two files normalized into one, as camel validate normalize a.yaml
b.yaml does: the onException of the
+ // second file must come before the route of the first one, or the
dump does not load
+ loadRoutes("""
+ - route:
+ id: first
+ from:
+ uri: direct:first
+ steps:
+ - to: mock:first
+ """, """
+ - onException:
+ exception:
+ - java.lang.Exception
+ handled:
+ constant:
+ expression: "true"
+ steps:
+ - to: mock:error
+ - route:
+ id: second
+ from:
+ uri: direct:second
+ steps:
+ - to: mock:second
+ """);
+
+ Path output = dir.resolve("normalized.yaml");
+ List<String> warnings = new ArrayList<>();
+ dumpRoutesToFile(output, new ArrayList<>(), warnings);
+ String yaml = Files.readString(output);
+
+ assertThat(yaml).startsWith("- onException:");
+ assertThat(yaml.split("onException:", -1)).hasSize(2);
+ assertThat(yaml).contains("id: first", "id: second");
+
+ // the user is told that the onException of the second file applies to
the route of the first file as well
+
assertThat(warnings).singleElement().asString().contains("route-1.yaml").doesNotContain("route-0.yaml");
+
+ // the combined dump is valid for the YAML DSL schema and loads
+
assertThat(context.getRouteDefinition("first").getOutputs()).noneMatch(OnExceptionDefinition.class::isInstance);
+
context.removeRouteDefinitions(List.copyOf(context.getRouteDefinitions()));
+ loadRoutes(yaml);
+ assertThat(context.getRouteDefinitions()).hasSize(2);
+ // the top-level onException of the second file now applies to the
route of the first file as well
+
assertThat(context.getRouteDefinition("first").getOutputs().get(0)).isInstanceOf(OnExceptionDefinition.class);
+ }
+
+ @Test
+ void routesOfOneFileDumpedIntoOneFileKeepTheirSource(@TempDir Path dir)
throws Exception {
+ loadRoutes("""
+ - onException:
+ exception:
+ - java.lang.Exception
+ handled:
+ constant:
+ expression: "true"
+ steps:
+ - to: mock:error
+ - route:
+ id: first
+ from:
+ uri: direct:first
+ steps:
+ - to: mock:first
+ """);
+
+ Path output = dir.resolve("normalized.yaml");
+ List<Resource> resources = new ArrayList<>();
+ List<String> warnings = new ArrayList<>();
+ dumpRoutesToFile(output, resources, warnings);
+
+ // the routes are dumped with their resource, so the log shows its
source, and there is no scope to warn about
+
assertThat(resources).singleElement().extracting(Resource::getLocation).isEqualTo("route-0.yaml");
+ assertThat(warnings).isEmpty();
+ }
+
+ private void dumpRoutesToFile(Path output, List<Resource> resources,
List<String> warnings) {
+ AbstractAppender appender = new AbstractAppender("dump-routes", null,
null, false, Property.EMPTY_ARRAY) {
+ @Override
+ public void append(LogEvent event) {
+ if (event.getLevel() == Level.WARN) {
+ warnings.add(event.getMessage().getFormattedMessage());
+ }
+ }
+ };
+ appender.start();
+ Logger logger = (Logger)
LogManager.getLogger(DefaultDumpRoutesStrategy.class);
+ logger.addAppender(appender);
+ try {
+ DefaultDumpRoutesStrategy dump = new DefaultDumpRoutesStrategy() {
+ @Override
+ protected void doDumpYaml(
+ CamelContext camelContext, NamedNode def, Resource
resource, ModelToYAMLDumper dumper,
+ String kind, StringBuilder sbLocal, StringBuilder
sbLog) {
+ resources.add(resource);
+ super.doDumpYaml(camelContext, def, resource, dumper,
kind, sbLocal, sbLog);
+ }
+ };
+ dump.setCamelContext(context);
+ dump.setInclude("routes");
+ dump.setLog(false);
+ dump.setUriAsParameters(true);
+ dump.setOutput(output.toString());
+ dump.dumpRoutes("yaml");
+ } finally {
+ logger.removeAppender(appender);
+ appender.stop();
+ }
+ }
+
+ private String dumpRoutes() throws Exception {
+ // as the routes are dumped by camel.main.dumpRoutes, which camel
validate normalize uses
+ RoutesDefinition routes = new RoutesDefinition();
+ for (RouteDefinition route : context.getRouteDefinitions()) {
+ routes.getRoutes().add(route);
+ }
+ return new LwModelToYAMLDumper().dumpModelAsYaml(context, routes,
false, true, false, false);
+ }
+}