This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch worktree-feature+CAMEL-23771-java-dsl-dump in repository https://gitbox.apache.org/repos/asf/camel.git
commit 64d9e32456fc80b586b93538a3c34afc5ed568e0 Author: Claus Ibsen <[email protected]> AuthorDate: Tue Jun 16 14:42:38 2026 +0200 CAMEL-23771: Add Java DSL dump support to SPI, JMX, DevConsole, CLI, and MCP Co-Authored-By: Claude <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- bom/camel-bom/pom.xml | 5 + .../main/java/org/apache/camel/CamelContext.java | 8 +- .../org/apache/camel/spi/DumpRoutesStrategy.java | 2 +- .../org/apache/camel/spi/ModelToJavaDumper.java | 59 +++++++ .../camel/impl/engine/AbstractCamelContext.java | 4 + .../camel/impl/engine/SimpleCamelContext.java | 9 + .../org/apache/camel/dev-console/route-dump.json | 2 +- .../camel/impl/console/RouteDumpDevConsole.java | 13 +- .../camel/impl/DefaultDumpRoutesStrategy.java | 143 ++++++++++++++++ .../services/org/apache/camel/modeljava-dumper | 2 + .../org/apache/camel/java/LwModelToJavaDumper.java | 184 +++++++++++++++++++++ .../camel-main-configuration-metadata.json | 2 +- core/camel-main/src/main/docs/main.adoc | 2 +- .../camel/main/DefaultConfigurationProperties.java | 12 +- .../management/mbean/ManagedCamelContextMBean.java | 6 + .../api/management/mbean/ManagedRouteMBean.java | 6 + .../management/mbean/ManagedCamelContext.java | 18 ++ .../camel/management/mbean/ManagedRoute.java | 16 ++ .../org/apache/camel/support/PluginHelper.java | 17 +- .../jbang-commands/camel-jbang-get-route-dump.adoc | 4 +- .../ROOT/pages/jbang-commands/camel-jbang-get.adoc | 2 +- .../META-INF/camel-jbang-commands-metadata.json | 2 +- .../core/commands/action/CamelRouteDumpAction.java | 6 +- .../dsl/jbang/core/commands/mcp/RuntimeTools.java | 4 +- dsl/camel-kamelet-main/pom.xml | 4 + .../camel-main-known-dependencies.properties | 1 + parent/pom.xml | 5 + 27 files changed, 513 insertions(+), 25 deletions(-) diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml index f58c1f690ef4..f8f0e315e4a8 100644 --- a/bom/camel-bom/pom.xml +++ b/bom/camel-bom/pom.xml @@ -1262,6 +1262,11 @@ <artifactId>camel-jasypt</artifactId> <version>4.21.0-SNAPSHOT</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-java-io</artifactId> + <version>4.21.0-SNAPSHOT</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-java-joor-dsl</artifactId> diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java index 3fac54babeb1..4157100fface 100644 --- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java +++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java @@ -1714,16 +1714,18 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio /** * If dumping is enabled then Camel will during startup dump all loaded routes (incl rests and route templates) - * represented as XML/YAML DSL into the log. This is intended for trouble shooting or to assist during development. + * represented as XML, YAML, or Java DSL into the log. This is intended for trouble shooting or to assist during + * development. * * Sensitive information that may be configured in the route endpoints could potentially be included in the dump * output and is therefore not recommended being used for production usage. * - * This requires to have camel-xml-io/camel-yaml-io on the classpath to be able to dump the routes as XML/YAML. + * This requires to have camel-xml-io/camel-yaml-io/camel-java-io on the classpath to be able to dump the routes as + * XML/YAML/Java. * * Using json is a special feature to dump route structure in JSon which can be useful for tooling. * - * @param format xml, yaml or json (additional configuration can be specified using query parameters, eg + * @param format xml, yaml, java, or json (additional configuration can be specified using query parameters, eg * ?include=all&uriAsParameters=true) */ void setDumpRoutes(@Nullable String format); diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/DumpRoutesStrategy.java b/core/camel-api/src/main/java/org/apache/camel/spi/DumpRoutesStrategy.java index d60b3f59ce82..fe58d62091eb 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/DumpRoutesStrategy.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/DumpRoutesStrategy.java @@ -33,7 +33,7 @@ public interface DumpRoutesStrategy extends StaticService { /** * Dump routes * - * @param format xml or yaml (json for route structure) + * @param format xml, yaml, or java (json for route structure) */ void dumpRoutes(String format); diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ModelToJavaDumper.java b/core/camel-api/src/main/java/org/apache/camel/spi/ModelToJavaDumper.java new file mode 100644 index 000000000000..c8080cd1e19b --- /dev/null +++ b/core/camel-api/src/main/java/org/apache/camel/spi/ModelToJavaDumper.java @@ -0,0 +1,59 @@ +/* + * 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.spi; + +import org.apache.camel.CamelContext; +import org.apache.camel.NamedNode; + +/** + * SPI for dumping model definitions into Java DSL representation. + * + * @since 4.21 + */ +public interface ModelToJavaDumper { + + /** + * Service factory key. + */ + String FACTORY = "modeljava-dumper"; + + /** + * Dumps the definition as Java DSL + * + * @param context the CamelContext + * @param definition the definition, such as a {@link NamedNode} + * @return the output in Java DSL (is formatted) + * @throws Exception is throw if error marshalling to Java DSL + */ + String dumpModelAsJava(CamelContext context, NamedNode definition) throws Exception; + + /** + * Dumps the definition as Java DSL + * + * @param context the CamelContext + * @param definition the definition, such as a {@link NamedNode} + * @param resolvePlaceholders whether to resolve property placeholders in the dumped Java DSL + * @param generatedIds whether to include auto generated IDs + * @return the output in Java DSL (is formatted) + * @throws Exception is throw if error marshalling to Java DSL + */ + String dumpModelAsJava( + CamelContext context, NamedNode definition, + boolean resolvePlaceholders, boolean generatedIds) + throws Exception; + +} diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java index d2b056f2ff58..c07f7b7bafef 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java @@ -139,6 +139,7 @@ import org.apache.camel.spi.ManagementStrategy; import org.apache.camel.spi.MessageHistoryFactory; import org.apache.camel.spi.MessageSizeStrategy; import org.apache.camel.spi.ModelJAXBContextFactory; +import org.apache.camel.spi.ModelToJavaDumper; import org.apache.camel.spi.ModelToStructureDumper; import org.apache.camel.spi.ModelToXMLDumper; import org.apache.camel.spi.ModelToYAMLDumper; @@ -405,6 +406,7 @@ public abstract class AbstractCamelContext extends BaseService camelContextExtension.lazyAddContextPlugin(BeanProcessorFactory.class, this::createBeanProcessorFactory); camelContextExtension.lazyAddContextPlugin(ModelToXMLDumper.class, this::createModelToXMLDumper); camelContextExtension.lazyAddContextPlugin(ModelToYAMLDumper.class, this::createModelToYAMLDumper); + camelContextExtension.lazyAddContextPlugin(ModelToJavaDumper.class, this::createModelToJavaDumper); camelContextExtension.lazyAddContextPlugin(ModelToStructureDumper.class, this::createModelToStructureDumper); camelContextExtension.lazyAddContextPlugin(DeferServiceFactory.class, this::createDeferServiceFactory); camelContextExtension.lazyAddContextPlugin(AnnotationBasedProcessorFactory.class, @@ -4592,6 +4594,8 @@ public abstract class AbstractCamelContext extends BaseService protected abstract ModelToYAMLDumper createModelToYAMLDumper(); + protected abstract ModelToJavaDumper createModelToJavaDumper(); + protected abstract ModelToStructureDumper createModelToStructureDumper(); protected abstract RestBindingJaxbDataFormatFactory createRestBindingJaxbDataFormatFactory(); diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java index bbef1f98be5a..8fe587dd8baa 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java @@ -71,6 +71,7 @@ import org.apache.camel.spi.ManagementNameStrategy; import org.apache.camel.spi.MessageHistoryFactory; import org.apache.camel.spi.MessageSizeStrategy; import org.apache.camel.spi.ModelJAXBContextFactory; +import org.apache.camel.spi.ModelToJavaDumper; import org.apache.camel.spi.ModelToStructureDumper; import org.apache.camel.spi.ModelToXMLDumper; import org.apache.camel.spi.ModelToYAMLDumper; @@ -552,6 +553,14 @@ public class SimpleCamelContext extends AbstractCamelContext { "camel-yaml-io"); } + @Override + protected ModelToJavaDumper createModelToJavaDumper() { + return ResolverHelper.resolveMandatoryBootstrapService(getCamelContextReference(), + ModelToJavaDumper.FACTORY, + ModelToJavaDumper.class, + "camel-java-io"); + } + @Override protected ModelToStructureDumper createModelToStructureDumper() { return ResolverHelper.resolveMandatoryBootstrapService(getCamelContextReference(), diff --git a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route-dump.json b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route-dump.json index 8fe9c46e8fd9..97dc896314d6 100644 --- a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route-dump.json +++ b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route-dump.json @@ -4,7 +4,7 @@ "group": "camel", "name": "route-dump", "title": "Route Dump", - "description": "Dump route in XML or YAML format", + "description": "Dump route in XML, YAML, or Java DSL format", "deprecated": false, "javaType": "org.apache.camel.impl.console.RouteDumpDevConsole", "groupId": "org.apache.camel", diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java index e7b68689c199..01db8c942baa 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDumpDevConsole.java @@ -40,7 +40,7 @@ import org.apache.camel.util.json.JsonArray; import org.apache.camel.util.json.JsonObject; import org.apache.camel.util.json.Jsoner; -@DevConsole(name = "route-dump", description = "Dump route in XML or YAML format") +@DevConsole(name = "route-dump", description = "Dump route in XML, YAML, or Java DSL format") public class RouteDumpDevConsole extends AbstractDevConsole { private static final Pattern XML_SOURCE_LOCATION_PATTERN = Pattern.compile("(\\ssourceLocation=\"(.*?)\")"); @@ -67,7 +67,7 @@ public class RouteDumpDevConsole extends AbstractDevConsole { public static final String URI_AS_PARAMETERS = "uriAsParameters"; public RouteDumpDevConsole() { - super("camel", "route-dump", "Route Dump", "Dump route in XML or YAML format"); + super("camel", "route-dump", "Route Dump", "Dump route in XML, YAML, or Java DSL format"); } @Override @@ -83,6 +83,8 @@ public class RouteDumpDevConsole extends AbstractDevConsole { dump = mrb.dumpRouteAsXml(true); } else if ("yaml".equals(format)) { dump = mrb.dumpRouteAsYaml(true, "true".equals(uriAsParameters)); + } else if ("java".equals(format)) { + dump = mrb.dumpRouteAsJava(true); } } catch (Exception e) { // ignore @@ -132,13 +134,16 @@ public class RouteDumpDevConsole extends AbstractDevConsole { } else if ("yaml".equals(format)) { jo.put("format", "yaml"); dump = mrb.dumpRouteAsYaml(true, "true".equals(uriAsParameters), false, true); + } else if ("java".equals(format)) { + jo.put("format", "java"); + dump = mrb.dumpRouteAsJava(true); } if (dump != null) { JsonArray code; if (format == null || "xml".equals(format)) { code = xmlLoadSourceAsJson(new StringReader(dump)); } else { - code = yamlLoadSourceAsJson(new StringReader(dump)); + code = javaOrYamlLoadSourceAsJson(new StringReader(dump)); } if (code != null) { jo.put("code", code); @@ -226,7 +231,7 @@ public class RouteDumpDevConsole extends AbstractDevConsole { return code.isEmpty() ? null : code; } - private static JsonArray yamlLoadSourceAsJson(Reader reader) { + private static JsonArray javaOrYamlLoadSourceAsJson(Reader reader) { JsonArray code = new JsonArray(); try { LineNumberReader lnr = new LineNumberReader(reader); 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 78221765535e..4a3fb4211e3e 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 @@ -44,6 +44,7 @@ import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.model.rest.RestsDefinition; import org.apache.camel.spi.DumpRoutesStrategy; import org.apache.camel.spi.ModelDumpLine; +import org.apache.camel.spi.ModelToJavaDumper; import org.apache.camel.spi.ModelToStructureDumper; import org.apache.camel.spi.ModelToXMLDumper; import org.apache.camel.spi.ModelToYAMLDumper; @@ -176,6 +177,8 @@ public class DefaultDumpRoutesStrategy extends ServiceSupport implements DumpRou doDumpRoutesAsYaml(camelContext); } else if ("xml".equalsIgnoreCase(format)) { doDumpRoutesAsXml(camelContext); + } else if ("java".equalsIgnoreCase(format)) { + doDumpRoutesAsJava(camelContext); } else if ("json".equals(format)) { doDumpRoutesStructureAsJSon(camelContext); } else if ("png".equals(format)) { @@ -451,6 +454,146 @@ public class DefaultDumpRoutesStrategy extends ServiceSupport implements DumpRou } + protected void doDumpRoutesAsJava(CamelContext camelContext) { + final ModelToJavaDumper dumper = PluginHelper.getModelToJavaDumper(camelContext); + final Model model = camelContext.getCamelContextExtension().getContextPlugin(Model.class); + final DummyResource dummy = new DummyResource(null, null); + final Set<String> files = new HashSet<>(); + + if (include.contains("*") || include.contains("all") || include.contains("rests")) { + int size = model.getRestDefinitions().size(); + if (size > 0) { + Map<Resource, RestsDefinition> groups = new LinkedHashMap<>(); + for (RestDefinition rest : model.getRestDefinitions()) { + Resource res = rest.getResource(); + if (res == null) { + res = dummy; + } + RestsDefinition rests = groups.computeIfAbsent(res, resource -> new RestsDefinition()); + rests.getRests().add(rest); + } + StringBuilder sbLog = new StringBuilder(); + for (Map.Entry<Resource, RestsDefinition> entry : groups.entrySet()) { + RestsDefinition def = entry.getValue(); + Resource resource = entry.getKey(); + + StringBuilder sbLocal = new StringBuilder(); + doDumpJava(camelContext, def, resource == dummy ? null : resource, dumper, "rests", sbLocal, sbLog); + doDumpToDirectory(resource, sbLocal, "rests", "java", files); + } + if (!sbLog.isEmpty() && log) { + LOG.info("Dumping {} rests as Java", size); + LOG.info("{}", sbLog); + } + } + } + + if (include.contains("*") || include.contains("all") || include.contains("routeConfigurations") + || include.contains("route-configurations")) { + int size = model.getRouteConfigurationDefinitions().size(); + if (size > 0) { + Map<Resource, RouteConfigurationsDefinition> groups = new LinkedHashMap<>(); + for (RouteConfigurationDefinition config : model.getRouteConfigurationDefinitions()) { + Resource res = config.getResource(); + if (res == null) { + res = dummy; + } + RouteConfigurationsDefinition routes + = groups.computeIfAbsent(res, resource -> new RouteConfigurationsDefinition()); + routes.getRouteConfigurations().add(config); + } + StringBuilder sbLog = new StringBuilder(); + for (Map.Entry<Resource, RouteConfigurationsDefinition> entry : groups.entrySet()) { + RouteConfigurationsDefinition def = entry.getValue(); + Resource resource = entry.getKey(); + + StringBuilder sbLocal = new StringBuilder(); + doDumpJava(camelContext, def, resource == dummy ? null : resource, dumper, "route-configurations", sbLocal, + sbLog); + doDumpToDirectory(resource, sbLocal, "route-configurations", "java", files); + } + if (!sbLog.isEmpty() && log) { + LOG.info("Dumping {} route-configurations as Java", size); + LOG.info("{}", sbLog); + } + } + } + + if (include.contains("*") || include.contains("all") || include.contains("routeTemplates") + || include.contains("route-templates")) { + int size = model.getRouteTemplateDefinitions().size(); + if (size > 0) { + Map<Resource, RouteTemplatesDefinition> groups = new LinkedHashMap<>(); + for (RouteTemplateDefinition rt : model.getRouteTemplateDefinitions()) { + Resource res = rt.getResource(); + if (res == null) { + res = dummy; + } + RouteTemplatesDefinition rests = groups.computeIfAbsent(res, resource -> new RouteTemplatesDefinition()); + rests.getRouteTemplates().add(rt); + } + StringBuilder sbLog = new StringBuilder(); + for (Map.Entry<Resource, RouteTemplatesDefinition> entry : groups.entrySet()) { + RouteTemplatesDefinition def = entry.getValue(); + Resource resource = entry.getKey(); + + StringBuilder sbLocal = new StringBuilder(); + doDumpJava(camelContext, def, resource == dummy ? null : resource, dumper, "route-templates", sbLocal, + sbLog); + doDumpToDirectory(resource, sbLocal, "route-templates", "java", files); + } + if (!sbLog.isEmpty() && log) { + LOG.info("Dumping {} route-templates as Java", size); + LOG.info("{}", sbLog); + } + } + } + + if (include.contains("*") || include.contains("all") || include.contains("routes")) { + int size = model.getRouteDefinitions().size(); + if (size > 0) { + Map<Resource, RoutesDefinition> groups = new LinkedHashMap<>(); + for (RouteDefinition route : model.getRouteDefinitions()) { + if ((route.isRest() != null && route.isRest()) || (route.isTemplate() != null && route.isTemplate())) { + continue; + } + Resource res = route.getResource(); + if (res == null) { + res = dummy; + } + RoutesDefinition routes = groups.computeIfAbsent(res, resource -> new RoutesDefinition()); + routes.getRoutes().add(route); + } + StringBuilder sbLog = new StringBuilder(); + for (Map.Entry<Resource, RoutesDefinition> entry : groups.entrySet()) { + RoutesDefinition def = entry.getValue(); + Resource resource = entry.getKey(); + + StringBuilder sbLocal = new StringBuilder(); + doDumpJava(camelContext, def, resource == dummy ? null : resource, dumper, "routes", sbLocal, sbLog); + doDumpToDirectory(resource, sbLocal, "routes", "java", files); + } + if (!sbLog.isEmpty() && log) { + LOG.info("Dumping {} routes as Java", size); + LOG.info("{}", sbLog); + } + } + } + + } + + protected void doDumpJava( + CamelContext camelContext, NamedNode def, Resource resource, + ModelToJavaDumper dumper, String kind, StringBuilder sbLocal, StringBuilder sbLog) { + try { + String dump = dumper.dumpModelAsJava(camelContext, def, resolvePlaceholders, generatedIds); + sbLocal.append(dump); + appendLogDump(resource, dump, sbLog); + } catch (Exception e) { + LOG.warn("Error dumping {}} to Java due to {}. This exception is ignored.", kind, e.getMessage(), e); + } + } + protected void doDumpYaml( CamelContext camelContext, NamedNode def, Resource resource, ModelToYAMLDumper dumper, String kind, StringBuilder sbLocal, StringBuilder sbLog) { diff --git a/core/camel-java-io/src/generated/resources/META-INF/services/org/apache/camel/modeljava-dumper b/core/camel-java-io/src/generated/resources/META-INF/services/org/apache/camel/modeljava-dumper new file mode 100644 index 000000000000..4b977fcd082d --- /dev/null +++ b/core/camel-java-io/src/generated/resources/META-INF/services/org/apache/camel/modeljava-dumper @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.java.LwModelToJavaDumper diff --git a/core/camel-java-io/src/main/java/org/apache/camel/java/LwModelToJavaDumper.java b/core/camel-java-io/src/main/java/org/apache/camel/java/LwModelToJavaDumper.java new file mode 100644 index 000000000000..ef9705f33c16 --- /dev/null +++ b/core/camel-java-io/src/main/java/org/apache/camel/java/LwModelToJavaDumper.java @@ -0,0 +1,184 @@ +/* + * 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.java; + +import java.util.Collection; +import java.util.Properties; + +import org.apache.camel.CamelContext; +import org.apache.camel.NamedNode; +import org.apache.camel.model.FromDefinition; +import org.apache.camel.model.RouteConfigurationDefinition; +import org.apache.camel.model.RouteConfigurationsDefinition; +import org.apache.camel.model.RouteDefinition; +import org.apache.camel.model.RouteTemplateDefinition; +import org.apache.camel.model.RouteTemplatesDefinition; +import org.apache.camel.model.RoutesDefinition; +import org.apache.camel.model.SendDefinition; +import org.apache.camel.model.ToDynamicDefinition; +import org.apache.camel.model.rest.RestConfigurationDefinition; +import org.apache.camel.model.rest.RestDefinition; +import org.apache.camel.model.rest.RestsDefinition; +import org.apache.camel.model.transformer.TransformerDefinition; +import org.apache.camel.model.transformer.TransformersDefinition; +import org.apache.camel.model.validator.ValidatorDefinition; +import org.apache.camel.model.validator.ValidatorsDefinition; +import org.apache.camel.spi.ModelToJavaDumper; +import org.apache.camel.spi.annotations.JdkService; + +import static org.apache.camel.model.ProcessorDefinitionHelper.filterTypeInOutputs; + +/** + * Lightweight {@link ModelToJavaDumper} based on the generated {@link org.apache.camel.java.out.JavaDslModelWriter}. + */ +@JdkService(ModelToJavaDumper.FACTORY) +public class LwModelToJavaDumper implements ModelToJavaDumper { + + @Override + public String dumpModelAsJava(CamelContext context, NamedNode definition) throws Exception { + return dumpModelAsJava(context, definition, false, true); + } + + @Override + public String dumpModelAsJava( + CamelContext context, NamedNode definition, + boolean resolvePlaceholders, boolean generatedIds) + throws Exception { + + Properties properties = new Properties(); + if (definition instanceof RouteTemplatesDefinition templates) { + templates.getRouteTemplates().forEach(template -> { + resolveEndpointDslUris(template.getRoute()); + collectTemplateProperties(template, properties); + }); + } else if (definition instanceof RouteTemplateDefinition template) { + resolveEndpointDslUris(template.getRoute()); + collectTemplateProperties(template, properties); + } else if (definition instanceof RoutesDefinition routes) { + routes.getRoutes().forEach(LwModelToJavaDumper::resolveEndpointDslUris); + } else if (definition instanceof RouteDefinition route) { + resolveEndpointDslUris(route); + } + + org.apache.camel.java.out.JavaDslModelWriter writer = new org.apache.camel.java.out.JavaDslModelWriter(); + + StringBuilder sb = new StringBuilder(); + if (definition instanceof RoutesDefinition rd) { + for (RouteDefinition route : rd.getRoutes()) { + if (!sb.isEmpty()) { + sb.append("\n\n"); + } + sb.append(writer.writeRouteDefinition(route)); + } + } else if (definition instanceof RouteDefinition route) { + sb.append(writer.writeRouteDefinition(route)); + } else if (definition instanceof RouteTemplatesDefinition rtd) { + for (RouteTemplateDefinition template : rtd.getRouteTemplates()) { + if (!sb.isEmpty()) { + sb.append("\n\n"); + } + sb.append(writer.writeRouteTemplateDefinition(template)); + } + } else if (definition instanceof RouteTemplateDefinition template) { + sb.append(writer.writeRouteTemplateDefinition(template)); + } else if (definition instanceof RestsDefinition rd) { + for (RestDefinition rest : rd.getRests()) { + if (!sb.isEmpty()) { + sb.append("\n\n"); + } + sb.append(writer.writeRestDefinition(rest)); + } + } else if (definition instanceof RestDefinition rest) { + sb.append(writer.writeRestDefinition(rest)); + } else if (definition instanceof RouteConfigurationsDefinition rcd) { + for (RouteConfigurationDefinition config : rcd.getRouteConfigurations()) { + if (!sb.isEmpty()) { + sb.append("\n\n"); + } + sb.append(writer.writeRouteConfigurationDefinition(config)); + } + } else if (definition instanceof RouteConfigurationDefinition config) { + sb.append(writer.writeRouteConfigurationDefinition(config)); + } else if (definition instanceof RestConfigurationDefinition restConfig) { + sb.append(writer.writeRestConfigurationDefinition(restConfig)); + } else if (definition instanceof TransformersDefinition td) { + for (TransformerDefinition t : td.getTransformers()) { + if (!sb.isEmpty()) { + sb.append("\n\n"); + } + sb.append(writer.writeTransformer(t)); + } + } else if (definition instanceof ValidatorsDefinition vd) { + for (ValidatorDefinition v : vd.getValidators()) { + if (!sb.isEmpty()) { + sb.append("\n\n"); + } + sb.append(writer.writeValidator(v)); + } + } + + String result = sb.toString(); + if (resolvePlaceholders) { + result = resolvePlaceholders(context, result, properties); + } + + return result; + } + + private static void collectTemplateProperties(RouteTemplateDefinition template, Properties properties) { + if (Boolean.TRUE.equals(template.getRoute().isTemplate())) { + java.util.Map<String, Object> parameters = template.getRoute().getTemplateParameters(); + if (parameters != null) { + properties.putAll(parameters); + } + } + } + + @SuppressWarnings("rawtypes") + private static void resolveEndpointDslUris(RouteDefinition route) { + if (route == null) { + return; + } + FromDefinition from = route.getInput(); + if (from != null && from.getEndpointConsumerBuilder() != null) { + from.setUri(from.getEndpointConsumerBuilder().getRawUri()); + } + Collection<SendDefinition> col = filterTypeInOutputs(route.getOutputs(), SendDefinition.class); + for (SendDefinition<?> to : col) { + if (to.getEndpointProducerBuilder() != null) { + to.setUri(to.getEndpointProducerBuilder().getRawUri()); + } + } + Collection<ToDynamicDefinition> col2 = filterTypeInOutputs(route.getOutputs(), ToDynamicDefinition.class); + for (ToDynamicDefinition to : col2) { + if (to.getEndpointProducerBuilder() != null) { + to.setUri(to.getEndpointProducerBuilder().getRawUri()); + } + } + } + + private static String resolvePlaceholders(CamelContext context, String text, Properties properties) { + context.getPropertiesComponent().setLocalProperties(properties); + try { + return context.resolvePropertyPlaceholders(text); + } catch (Exception e) { + return text; + } finally { + context.getPropertiesComponent().setLocalProperties(null); + } + } +} diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index 887cc21c6825..e47ba7d7c622 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -56,7 +56,7 @@ { "name": "camel.main.contextReloadEnabled", "required": false, "description": "Used for enabling context reloading. If enabled then Camel allow external systems such as security vaults (AWS secrets manager, etc.) to trigger refreshing Camel by updating property placeholders and reload all existing routes to take changes into effect.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false }, { "name": "camel.main.description", "required": false, "description": "Sets the description (intended for humans) of the Camel application.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false }, { "name": "camel.main.devConsoleEnabled", "required": false, "description": "Whether to enable developer console (requires camel-console on classpath). The developer console is only for assisting during development. This is NOT for production usage.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false, "security": "insecure:dev" }, - { "name": "camel.main.dumpRoutes", "required": false, "description": "If dumping is enabled then Camel will during startup dump all loaded routes (incl rests and route templates) represented as XML\/YAML DSL into the log. This is intended for trouble shooting or to assist during development. Sensitive information that may be configured in the route endpoints could potentially be included in the dump output and is therefore not recommended being used for production usage. This require [...] + { "name": "camel.main.dumpRoutes", "required": false, "description": "If dumping is enabled then Camel will during startup dump all loaded routes (incl rests and route templates) represented as XML, YAML, or Java DSL into the log. This is intended for trouble shooting or to assist during development. Sensitive information that may be configured in the route endpoints could potentially be included in the dump output and is therefore not recommended being used for production usage. Thi [...] { "name": "camel.main.dumpRoutesGeneratedIds", "required": false, "description": "Whether to include auto generated IDs in the dumped output. Default is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false }, { "name": "camel.main.dumpRoutesInclude", "required": false, "description": "Controls what to include in output for route dumping. Possible values: all, routes, rests, routeConfigurations, routeTemplates, beans, dataFormats. Multiple values can be separated by comma. Default is routes.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "routes", "secret": false }, { "name": "camel.main.dumpRoutesLog", "required": false, "description": "Whether to log route dumps to Logger", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true, "secret": false }, diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index 890332adbfe5..6dc9f34881fa 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -49,7 +49,7 @@ The camel.main supports 129 options, which are listed below. | *camel.main.contextReloadEnabled* | Used for enabling context reloading. If enabled then Camel allow external systems such as security vaults (AWS secrets manager, etc.) to trigger refreshing Camel by updating property placeholders and reload all existing routes to take changes into effect. | false | boolean | *camel.main.description* | Sets the description (intended for humans) of the Camel application. | | String | *camel.main.devConsoleEnabled* | Whether to enable developer console (requires camel-console on classpath). The developer console is only for assisting during development. This is NOT for production usage. | false | boolean -| *camel.main.dumpRoutes* | If dumping is enabled then Camel will during startup dump all loaded routes (incl rests and route templates) represented as XML/YAML DSL into the log. This is intended for trouble shooting or to assist during development. Sensitive information that may be configured in the route endpoints could potentially be included in the dump output and is therefore not recommended being used for production usage. This requires to have camel-xml-io/camel-yaml-io on the cla [...] +| *camel.main.dumpRoutes* | If dumping is enabled then Camel will during startup dump all loaded routes (incl rests and route templates) represented as XML, YAML, or Java DSL into the log. This is intended for trouble shooting or to assist during development. Sensitive information that may be configured in the route endpoints could potentially be included in the dump output and is therefore not recommended being used for production usage. This requires to have camel-xml-io/camel-yaml-io/ [...] | *camel.main.dumpRoutesGeneratedIds* | Whether to include auto generated IDs in the dumped output. Default is false. | false | boolean | *camel.main.dumpRoutesInclude* | Controls what to include in output for route dumping. Possible values: all, routes, rests, routeConfigurations, routeTemplates, beans, dataFormats. Multiple values can be separated by comma. Default is routes. | routes | String | *camel.main.dumpRoutesLog* | Whether to log route dumps to Logger | true | boolean diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java index 42489e639866..3663ee3f1564 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java @@ -1540,12 +1540,14 @@ public abstract class DefaultConfigurationProperties<T> { /** * If dumping is enabled then Camel will during startup dump all loaded routes (incl rests and route templates) - * represented as XML/YAML DSL into the log. This is intended for trouble shooting or to assist during development. + * represented as XML, YAML, or Java DSL into the log. This is intended for trouble shooting or to assist during + * development. * * Sensitive information that may be configured in the route endpoints could potentially be included in the dump * output and is therefore not recommended being used for production usage. * - * This requires to have camel-xml-io/camel-yaml-io on the classpath to be able to dump the routes as XML/YAML. + * This requires to have camel-xml-io/camel-yaml-io/camel-java-io on the classpath to be able to dump the routes as + * XML/YAML/Java. * * You can also use JSon which dumps the route structure in JSon. The JSon does not represent Camel DSL but it * useful for tooling to understand the structure of the routes and how EIPs are nested together. @@ -2754,12 +2756,14 @@ public abstract class DefaultConfigurationProperties<T> { /** * If dumping is enabled then Camel will during startup dump all loaded routes (incl rests and route templates) - * represented as XML/YAML DSL into the log. This is intended for trouble shooting or to assist during development. + * represented as XML, YAML, or Java DSL into the log. This is intended for trouble shooting or to assist during + * development. * * Sensitive information that may be configured in the route endpoints could potentially be included in the dump * output and is therefore not recommended being used for production usage. * - * This requires to have camel-xml-io/camel-yaml-io on the classpath to be able to dump the routes as XML/YAML. + * This requires to have camel-xml-io/camel-yaml-io/camel-java-io on the classpath to be able to dump the routes as + * XML/YAML/Java. * * You can also use JSon which dumps the route structure in JSon. The JSon does not represent Camel DSL but it * useful for tooling to understand the structure of the routes and how EIPs are nested together. diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java index 28cdad9e6892..e396931362a0 100644 --- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java +++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java @@ -257,6 +257,12 @@ public interface ManagedCamelContextMBean extends ManagedPerformanceCounterMBean String dumpRoutesAsYaml(boolean resolvePlaceholders, boolean uriAsParameters, boolean generatedIds, boolean sourceLocation) throws Exception; + @ManagedOperation(description = "Dumps the routes as Java DSL") + String dumpRoutesAsJava() throws Exception; + + @ManagedOperation(description = "Dumps the routes as Java DSL") + String dumpRoutesAsJava(boolean resolvePlaceholders) throws Exception; + /** * Creates the endpoint by the given uri * diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java index cfc54f8118ec..0519b423ff8b 100644 --- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java +++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java @@ -155,6 +155,12 @@ public interface ManagedRouteMBean extends ManagedPerformanceCounterMBean { String dumpRouteAsYaml(boolean resolvePlaceholders, boolean uriAsParameters, boolean generatedIds, boolean sourceLocation) throws Exception; + @ManagedOperation(description = "Dumps the route as Java DSL") + String dumpRouteAsJava() throws Exception; + + @ManagedOperation(description = "Dumps the route as Java DSL") + String dumpRouteAsJava(boolean resolvePlaceholders) throws Exception; + @ManagedOperation(description = "Dumps the route stats as XML") String dumpRouteStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception; diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java index c495526f7821..37e8ab2c38ad 100644 --- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java +++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java @@ -635,6 +635,24 @@ public class ManagedCamelContext extends ManagedPerformanceCounter implements Ti generatedIds, sourceLocation); } + @Override + public String dumpRoutesAsJava() throws Exception { + return dumpRoutesAsJava(false); + } + + @Override + public String dumpRoutesAsJava(boolean resolvePlaceholders) throws Exception { + List<RouteDefinition> routes = context.getCamelContextExtension().getContextPlugin(Model.class).getRouteDefinitions(); + if (routes.isEmpty()) { + return null; + } + + RoutesDefinition def = new RoutesDefinition(); + def.setRoutes(routes); + + return PluginHelper.getModelToJavaDumper(context).dumpModelAsJava(context, def, resolvePlaceholders, true); + } + @Override public String dumpRouteTemplatesAsXml() throws Exception { List<RouteTemplateDefinition> templates diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java index 240b6d159239..deac037f2286 100644 --- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java +++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java @@ -494,6 +494,22 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList return null; } + @Override + public String dumpRouteAsJava() throws Exception { + return dumpRouteAsJava(false); + } + + @Override + public String dumpRouteAsJava(boolean resolvePlaceholders) throws Exception { + String id = route.getId(); + RouteDefinition def = context.getCamelContextExtension().getContextPlugin(Model.class).getRouteDefinition(id); + if (def != null) { + return PluginHelper.getModelToJavaDumper(context).dumpModelAsJava(context, def, resolvePlaceholders, true); + } + + return null; + } + @Override public String dumpRouteStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception { // in this logic we need to calculate the accumulated processing time for the processor in the route diff --git a/core/camel-support/src/main/java/org/apache/camel/support/PluginHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/PluginHelper.java index 99c33772c33c..e33122a682ed 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/PluginHelper.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/PluginHelper.java @@ -41,6 +41,7 @@ import org.apache.camel.spi.InterceptEndpointFactory; import org.apache.camel.spi.InternalProcessorFactory; import org.apache.camel.spi.LanguageResolver; import org.apache.camel.spi.ModelJAXBContextFactory; +import org.apache.camel.spi.ModelToJavaDumper; import org.apache.camel.spi.ModelToStructureDumper; import org.apache.camel.spi.ModelToXMLDumper; import org.apache.camel.spi.ModelToYAMLDumper; @@ -564,12 +565,26 @@ public final class PluginHelper { } /** - * Gets the {@link ModelToXMLDumper} to be used. + * Gets the {@link ModelToYAMLDumper} to be used. */ public static ModelToYAMLDumper getModelToYAMLDumper(ExtendedCamelContext extendedCamelContext) { return extendedCamelContext.getContextPlugin(ModelToYAMLDumper.class); } + /** + * Gets the {@link ModelToJavaDumper} to be used. + */ + public static ModelToJavaDumper getModelToJavaDumper(CamelContext camelContext) { + return getModelToJavaDumper(camelContext.getCamelContextExtension()); + } + + /** + * Gets the {@link ModelToJavaDumper} to be used. + */ + public static ModelToJavaDumper getModelToJavaDumper(ExtendedCamelContext extendedCamelContext) { + return extendedCamelContext.getContextPlugin(ModelToJavaDumper.class); + } + /** * Gets the {@link ModelToStructureDumper} to be used. */ diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route-dump.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route-dump.adoc index 8f1f3302eb40..1cc3cc3622c9 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route-dump.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route-dump.adoc @@ -2,7 +2,7 @@ // AUTO-GENERATED by camel-package-maven-plugin - DO NOT EDIT THIS FILE = camel get route-dump -Dump Camel route in XML or YAML format +Dump Camel route in XML, YAML, or Java DSL format == Usage @@ -20,7 +20,7 @@ camel get route-dump [options] |=== | Option | Description | Default | Type | `--filter` | Filter route by filename or route id (multiple names can be separated by comma) | | String -| `--format` | Output format (xml, or yaml) | yaml | String +| `--format` | Output format (xml, yaml, or java) | yaml | String | `--raw` | To output raw without metadata | | boolean | `--sort` | Sort route by name or id | name | String | `--uri-as-parameters` | Whether to expand URIs into separated key/value parameters (only in use for YAML format) | true | boolean diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get.adoc index 91dbbbb51184..e96ca2f286c1 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get.adoc @@ -42,7 +42,7 @@ camel get [options] | xref:jbang-commands/camel-jbang-get-rest.adoc[rest] | Get REST services of Camel integrations | xref:jbang-commands/camel-jbang-get-route.adoc[route] | Get status of Camel routes | xref:jbang-commands/camel-jbang-get-route-controller.adoc[route-controller] | List status of route controller -| xref:jbang-commands/camel-jbang-get-route-dump.adoc[route-dump] | Dump Camel route in XML or YAML format +| xref:jbang-commands/camel-jbang-get-route-dump.adoc[route-dump] | Dump Camel route in XML, YAML, or Java DSL format | xref:jbang-commands/camel-jbang-get-service.adoc[service] | Get services of Camel integrations | xref:jbang-commands/camel-jbang-get-source.adoc[source] | Display Camel route source code | xref:jbang-commands/camel-jbang-get-startup-recorder.adoc[startup-recorder] | Display startup recording diff --git a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json index 8ea30e87078f..0a818cf9c8f3 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json +++ b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json @@ -15,7 +15,7 @@ { "name": "eval", "fullName": "eval", "description": "Evaluate Camel expressions and scripts", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.EvalCommand", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "expression", "fullName": "eval expression", "description": "Evaluates Camel expression", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.EvalEx [...] { "name": "explain", "fullName": "explain", "description": "Explain what a Camel route does using AI\/LLM", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Explain", "options": [ { "names": "--api-key", "description": "API key for authentication. Also reads ANTHROPIC_API_KEY, OPENAI_API_KEY, or LLM_API_KEY env vars", "javaType": "java.lang.String", "type": "string" }, { "names": "--api-type", "description": "API type: 'ollama', 'openai' (OpenAI-compatible), or 'anthropic' (A [...] { "name": "export", "fullName": "export", "description": "Export to other runtimes (Camel Main, Spring Boot, or Quarkus)", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Export", "options": [ { "names": "--build-property", "description": "Maven build properties, ex. --build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { "names": "--camel-spring-boot-version", "description": "Camel version to use with Spring Boot", "javaType": "java.lang.String", "ty [...] - { "name": "get", "fullName": "get", "description": "Get status of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "bean", "fullName": "get [...] + { "name": "get", "fullName": "get", "description": "Get status of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "bean", "fullName": "get [...] { "name": "harden", "fullName": "harden", "description": "Suggest security hardening for Camel routes using AI\/LLM", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Harden", "options": [ { "names": "--api-key", "description": "API key for authentication. Also reads OPENAI_API_KEY or LLM_API_KEY env vars", "javaType": "java.lang.String", "type": "string" }, { "names": "--api-type", "description": "API type: 'ollama' or 'openai' (OpenAI-compatible)", "defaultValue": "ollama", [...] { "name": "hawtio", "fullName": "hawtio", "description": "Launch Hawtio web console", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Hawtio", "options": [ { "names": "--host", "description": "Hostname to bind the Hawtio web console to", "defaultValue": "127.0.0.1", "javaType": "java.lang.String", "type": "string" }, { "names": "--openUrl", "description": "To automatic open Hawtio web console in the web browser", "defaultValue": "true", "javaType": "boolean", "type": [...] { "name": "infra", "fullName": "infra", "description": "List and Run external services for testing and prototyping", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraCommand", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", "fullName": "infra [...] diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteDumpAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteDumpAction.java index 0bde02505a45..ccdb0c32984e 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteDumpAction.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteDumpAction.java @@ -35,7 +35,7 @@ import picocli.CommandLine.Command; import static org.apache.camel.support.LoggerHelper.stripSourceLocationLineNumber; -@Command(name = "route-dump", description = "Dump Camel route in XML or YAML format", sortOptions = false, +@Command(name = "route-dump", description = "Dump Camel route in XML, YAML, or Java DSL format", sortOptions = false, showDefaultValues = true, footer = { "%nExamples:", @@ -62,7 +62,7 @@ public class CamelRouteDumpAction extends ActionBaseCommand { @Override public Iterator<String> iterator() { - return List.of("yaml", "xml").iterator(); + return List.of("yaml", "xml", "java").iterator(); } } @@ -71,7 +71,7 @@ public class CamelRouteDumpAction extends ActionBaseCommand { String name = "*"; @CommandLine.Option(names = { "--format" }, completionCandidates = FormatCompletionCandidates.class, - description = "Output format (xml, or yaml)", defaultValue = "yaml") + description = "Output format (xml, yaml, or java)", defaultValue = "yaml") String format; @CommandLine.Option(names = { "--raw" }, diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/RuntimeTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/RuntimeTools.java index 2a00858f51d3..8c4eace1783a 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/RuntimeTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/RuntimeTools.java @@ -169,11 +169,11 @@ public class RuntimeTools { } @Tool(annotations = @Tool.Annotations(readOnlyHint = true, destructiveHint = false, openWorldHint = false), - description = "Dump route definitions in XML or YAML format.") + description = "Dump route definitions in XML, YAML, or Java DSL format.") public JsonObject camel_runtime_route_dump( @ToolArg(description = NAME_OR_PID_DESC) String nameOrPid, @ToolArg(description = "Route ID to dump (use * for all routes)") String routeId, - @ToolArg(description = "Output format: xml or yaml (default: yaml)") String format) { + @ToolArg(description = "Output format: xml, yaml, or java (default: yaml)") String format) { RuntimeService.ProcessInfo p = runtimeService.findSingleProcess(nameOrPid); return runtimeService.executeAction(p.pid(), "route-dump", root -> { root.put("id", routeId != null ? routeId : "*"); diff --git a/dsl/camel-kamelet-main/pom.xml b/dsl/camel-kamelet-main/pom.xml index 6201643b7f0f..d0967ea3e058 100644 --- a/dsl/camel-kamelet-main/pom.xml +++ b/dsl/camel-kamelet-main/pom.xml @@ -80,6 +80,10 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-xml-io</artifactId> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-java-io</artifactId> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-bean</artifactId> diff --git a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties index 1bdea3b54bbb..ac4afe0e433b 100644 --- a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties +++ b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties @@ -47,6 +47,7 @@ camel.telemetryDev = camel:telemetry-dev META-INF/services/org/apache/camel/modelxml-dumper = camel:xml-io META-INF/services/org/apache/camel/modelyaml-dumper = camel:yaml-io +META-INF/services/org/apache/camel/modeljava-dumper = camel:java-io META-INF/services/org/apache/camel/cron/cron-service = camel:quartz com.amazon.redshift.jdbc.Driver = com.amazon.redshift:redshift-jdbc42:2.1.0.33 diff --git a/parent/pom.xml b/parent/pom.xml index 49e2cee854ff..ba40f05a8664 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -662,6 +662,11 @@ <artifactId>camel-main</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-java-io</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-xml-io</artifactId>
