This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feature/CAMEL-23672-tui-diagram in repository https://gitbox.apache.org/repos/asf/camel.git
commit 8d336e72ef922b860c6f145484777d0a153dd9e3 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Jun 3 21:13:12 2026 +0200 CAMEL-23672: camel-tui - Single IPC call for topology + route structure Add routes=true option to route-topology dev console that includes route structure data in the same response, eliminating a second IPC round-trip when loading the TUI diagram tab. Co-Authored-By: Claude Opus 4.6 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../impl/console/RouteTopologyDevConsole.java | 20 +++++++++++ .../camel/cli/connector/LocalCliConnector.java | 4 ++- .../jbang/core/commands/tui/DiagramSupport.java | 42 ++++++++++++---------- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteTopologyDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteTopologyDevConsole.java index 0caa74155434..2645d206ea9a 100644 --- a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteTopologyDevConsole.java +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteTopologyDevConsole.java @@ -23,6 +23,7 @@ import java.util.Map; import org.apache.camel.api.management.ManagedCamelContext; import org.apache.camel.api.management.mbean.ManagedRouteMBean; import org.apache.camel.api.management.mbean.ManagedSendProcessorMBean; +import org.apache.camel.console.DevConsoleRegistry; import org.apache.camel.spi.RouteTopologyDumper; import org.apache.camel.spi.RouteTopologyDumper.TopologyEdge; import org.apache.camel.spi.RouteTopologyDumper.TopologyExternalEndpoint; @@ -40,6 +41,7 @@ public class RouteTopologyDevConsole extends AbstractDevConsole { private static final String METRIC = "metric"; private static final String EXTERNAL = "external"; + private static final String ROUTES = "routes"; public RouteTopologyDevConsole() { super("camel", "route-topology", "Route Topology", "Route topology showing inter-route connections"); @@ -166,6 +168,24 @@ public class RouteTopologyDevConsole extends AbstractDevConsole { root.put("externalEndpoints", extArr); } + // Optionally include route structure data in the same response + if ("true".equals(options.get(ROUTES))) { + DevConsoleRegistry registry = getCamelContext().getCamelContextExtension() + .getContextPlugin(DevConsoleRegistry.class); + if (registry != null) { + var structureConsole = registry.resolveById("route-structure"); + if (structureConsole != null) { + String metricStr = metric ? "true" : "false"; + JsonObject structureResult = (JsonObject) structureConsole.call( + org.apache.camel.console.DevConsole.MediaType.JSON, + Map.of("filter", "*", "brief", "false", "metric", metricStr)); + if (structureResult != null) { + root.put("routes", structureResult.get("routes")); + } + } + } + } + return root; } diff --git a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java index 91296898a42a..dfe522aa3af9 100644 --- a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java +++ b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java @@ -756,8 +756,10 @@ public class LocalCliConnector extends ServiceSupport implements CliConnector, C if (dc != null) { String metric = root.getStringOrDefault("metric", "false"); String external = root.getStringOrDefault("external", "false"); + String routes = root.getStringOrDefault("routes", "false"); JsonObject json - = (JsonObject) dc.call(DevConsole.MediaType.JSON, Map.of("metric", metric, "external", external)); + = (JsonObject) dc.call(DevConsole.MediaType.JSON, + Map.of("metric", metric, "external", external, "routes", routes)); LOG.trace("Updating output file: {}", outputFile); IOHelper.writeText(json.toJson(), outputFile); } else { diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java index 14c76243390b..340dcc7a2ef1 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java @@ -788,10 +788,8 @@ class DiagramSupport { void loadAllDiagramsInBackground( MonitorContext ctx, String pid, boolean metrics, boolean external) { - // Fetch topology - JsonObject topoJson = requestRouteTopology(ctx, pid, external); - // Fetch all route structures - JsonObject routeJson = requestRouteStructure(ctx, pid); + // Single IPC call: topology + route structures + JsonObject topoJson = requestRouteTopology(ctx, pid, external, true); TopologyLayoutResult topoResult = null; int nodeW = 0; @@ -813,20 +811,23 @@ class DiagramSupport { } } + // Route structure is included in the topology response (routes=true) java.util.Map<String, RouteDiagramLayoutEngine.LayoutRoute> routeMap = new java.util.LinkedHashMap<>(); - if (routeJson != null) { - List<RouteDiagramLayoutEngine.RouteInfo> routes = RouteDiagramHelper.parseRoutes(routeJson); - RouteDiagramLayoutEngine.NodeLabelMode labelMode = showDescription - ? RouteDiagramLayoutEngine.NodeLabelMode.DESCRIPTION - : RouteDiagramLayoutEngine.NodeLabelMode.CODE; - RouteDiagramLayoutEngine engine = new RouteDiagramLayoutEngine( - RouteDiagramLayoutEngine.DEFAULT_BOX_WIDTH, RouteDiagramLayoutEngine.DEFAULT_FONT_SIZE, - labelMode); - int currentY = RouteDiagramLayoutEngine.PADDING; - for (RouteDiagramLayoutEngine.RouteInfo r : routes) { - RouteDiagramLayoutEngine.LayoutRoute lr = engine.layoutRoute(r, currentY); - routeMap.put(r.routeId, lr); - currentY = lr.maxY + RouteDiagramLayoutEngine.V_GAP; + if (topoJson != null) { + List<RouteDiagramLayoutEngine.RouteInfo> routes = RouteDiagramHelper.parseRoutes(topoJson); + if (!routes.isEmpty()) { + RouteDiagramLayoutEngine.NodeLabelMode labelMode = showDescription + ? RouteDiagramLayoutEngine.NodeLabelMode.DESCRIPTION + : RouteDiagramLayoutEngine.NodeLabelMode.CODE; + RouteDiagramLayoutEngine engine = new RouteDiagramLayoutEngine( + RouteDiagramLayoutEngine.DEFAULT_BOX_WIDTH, RouteDiagramLayoutEngine.DEFAULT_FONT_SIZE, + labelMode); + int currentY = RouteDiagramLayoutEngine.PADDING; + for (RouteDiagramLayoutEngine.RouteInfo r : routes) { + RouteDiagramLayoutEngine.LayoutRoute lr = engine.layoutRoute(r, currentY); + routeMap.put(r.routeId, lr); + currentY = lr.maxY + RouteDiagramLayoutEngine.V_GAP; + } } } @@ -902,7 +903,7 @@ class DiagramSupport { void loadTopologyDiagramInBackground( MonitorContext ctx, String pid, boolean textMode, boolean metrics, boolean external) { - JsonObject jo = requestRouteTopology(ctx, pid, external); + JsonObject jo = requestRouteTopology(ctx, pid, external, false); if (jo == null) { applyResult(ctx, List.of("(No response from integration)"), null, null, null); return; @@ -987,7 +988,7 @@ class DiagramSupport { } } - private JsonObject requestRouteTopology(MonitorContext ctx, String pid, boolean external) { + private JsonObject requestRouteTopology(MonitorContext ctx, String pid, boolean external, boolean routes) { Path outputFile = ctx.getOutputFile(pid); PathUtils.deleteFile(outputFile); @@ -997,6 +998,9 @@ class DiagramSupport { if (external) { root.put("external", "true"); } + if (routes) { + root.put("routes", "true"); + } Path actionFile = ctx.getActionFile(pid); PathUtils.writeTextSafely(root.toJson(), actionFile);
