This is an automated email from the ASF dual-hosted git repository.
davsclaus 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 1bdee366d359 CAMEL-23400: camel-diagram - prepare for being used in
maven tooling and also as SPI in camel-core (#23074)
1bdee366d359 is described below
commit 1bdee366d35935bb9f86f659891d1b5a7e924bd8
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu May 7 19:27:20 2026 +0200
CAMEL-23400: camel-diagram - prepare for being used in maven tooling and
also as SPI in camel-core (#23074)
---
.../apache/camel/diagram/RouteDiagramHelper.java | 20 ++----
.../org/apache/camel/diagram/RouteDiagramTest.java | 4 +-
.../main/java/org/apache/camel/CamelContext.java | 5 ++
.../src/main/java/org/apache/camel/NamedRoute.java | 12 ++++
.../camel/impl/engine/AbstractCamelContext.java | 13 ++--
.../camel/impl/engine/SimpleCamelContext.java | 7 ++
.../impl/console/RouteStructureDevConsole.java | 75 +++++++++-------------
.../org/apache/camel/impl/DefaultCamelContext.java | 6 ++
.../org/apache/camel/support/LoggerHelper.java | 28 +++++++-
9 files changed, 101 insertions(+), 69 deletions(-)
diff --git
a/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
b/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
index eaff690ceb4b..5a3fe8b5028e 100644
---
a/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
+++
b/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
@@ -21,6 +21,8 @@ import java.util.List;
import org.apache.camel.diagram.RouteDiagramLayoutEngine.NodeInfo;
import org.apache.camel.diagram.RouteDiagramLayoutEngine.RouteInfo;
+import org.apache.camel.support.LoggerHelper;
+import org.apache.camel.util.FileUtil;
import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
import org.apache.camel.util.json.Jsoner;
@@ -86,21 +88,9 @@ public final class RouteDiagramHelper {
if (source == null || source.isBlank()) {
return null;
}
- // strip URI scheme prefix (e.g. "file:", "classpath:") — only if the
part
- // before the first colon is all letters (a valid scheme). This avoids
- // stripping line numbers from sources like "cheese.java:9".
- int colon = source.indexOf(':');
- if (colon > 0) {
- String scheme = source.substring(0, colon);
- if (scheme.chars().allMatch(Character::isLetter)) {
- source = source.substring(colon + 1);
- }
- }
- // return just the filename part
- int slash = Math.max(source.lastIndexOf('/'),
source.lastIndexOf('\\'));
- if (slash >= 0 && slash < source.length() - 1) {
- return source.substring(slash + 1);
- }
+ source = LoggerHelper.sourceNameOnly(source);
+ source = LoggerHelper.stripScheme(source);
+ source = FileUtil.stripPath(source);
return source;
}
}
diff --git
a/components/camel-diagram/src/test/java/org/apache/camel/diagram/RouteDiagramTest.java
b/components/camel-diagram/src/test/java/org/apache/camel/diagram/RouteDiagramTest.java
index a7ea8029bdd5..4f5e5cd86dca 100644
---
a/components/camel-diagram/src/test/java/org/apache/camel/diagram/RouteDiagramTest.java
+++
b/components/camel-diagram/src/test/java/org/apache/camel/diagram/RouteDiagramTest.java
@@ -818,12 +818,12 @@ class RouteDiagramTest {
@Test
void testExtractSourceNameWithLineNumber() {
- assertEquals("cheese.java:9",
RouteDiagramHelper.extractSourceName("cheese.java:9"));
+ assertEquals("cheese.java",
RouteDiagramHelper.extractSourceName("cheese.java:9"));
}
@Test
void testExtractSourceNameSchemeAndLineNumber() {
- assertEquals("cheese.java:9",
RouteDiagramHelper.extractSourceName("file:/path/to/cheese.java:9"));
+ assertEquals("cheese.java",
RouteDiagramHelper.extractSourceName("file:/path/to/cheese.java:9"));
}
@Test
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 46700aa30751..7f8ebdc2ac0e 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
@@ -790,6 +790,11 @@ public interface CamelContext extends
CamelContextLifecycle, RuntimeConfiguratio
*/
List<RoutePolicyFactory> getRoutePolicyFactories();
+ /**
+ * Gets a light-weight API for the route model defunitions.
+ */
+ List<NamedRoute> getNamedRouteDefinitions();
+
// Rest Methods
//-----------------------------------------------------------------------
diff --git a/core/camel-api/src/main/java/org/apache/camel/NamedRoute.java
b/core/camel-api/src/main/java/org/apache/camel/NamedRoute.java
index 047cd99be2db..017123bab68a 100644
--- a/core/camel-api/src/main/java/org/apache/camel/NamedRoute.java
+++ b/core/camel-api/src/main/java/org/apache/camel/NamedRoute.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel;
+import org.apache.camel.spi.Resource;
+
/**
* Represents a node in the {@link org.apache.camel.model routes} which is
identified as a route.
*/
@@ -26,6 +28,11 @@ public interface NamedRoute {
*/
String getRouteId();
+ /**
+ * Gets the route description.
+ */
+ String getDescription();
+
/**
* Gets the node prefix id.
*/
@@ -51,4 +58,9 @@ public interface NamedRoute {
*/
NamedNode getInput();
+ /**
+ * Gets the {@link Resource}.
+ */
+ Resource getResource();
+
}
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 7a50b8fdd244..a66f12105837 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
@@ -3176,6 +3176,12 @@ public abstract class AbstractCamelContext extends
BaseService
LOG.debug("Skip starting routes as CamelContext has been
configured with autoStartup=false");
}
+ // dump routes when as we have model before creating the runtime
models, which can help during troubleshooting
+ // when routes have problems starting
+ if (getDumpRoutes() != null && !"false".equals(getDumpRoutes())) {
+ doDumpRoutes();
+ }
+
if (!getRouteController().isSupervising()) {
// invoke this logic to warmup the routes and if possible also
start the routes (using default route controller)
StartupStep subStep
@@ -3187,13 +3193,6 @@ public abstract class AbstractCamelContext extends
BaseService
startupStepRecorder.endStep(subStep);
}
- // TODO: json,png should be later
- // dump routes when as we have model before creating the runtime
models, which can help during troubleshooting
- // when routes have problems starting
- if (getDumpRoutes() != null && !"false".equals(getDumpRoutes())) {
- doDumpRoutes();
- }
-
// ensure extra dev consoles is loaded in case additional JARs has
been dynamically added to the classpath
if (devConsole) {
StartupStep step =
startupStepRecorder.beginStep(CamelContext.class, null, "Scan DevConsoles
(phase 2)");
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 23db758d00d6..7bf67d739dd5 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
@@ -16,12 +16,14 @@
*/
package org.apache.camel.impl.engine;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
+import org.apache.camel.NamedRoute;
import org.apache.camel.Processor;
import org.apache.camel.Route;
import org.apache.camel.RouteTemplateContext;
@@ -774,6 +776,11 @@ public class SimpleCamelContext extends
AbstractCamelContext {
throw new UnsupportedOperationException();
}
+ @Override
+ public List<NamedRoute> getNamedRouteDefinitions() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String getTestExcludeRoutes() {
throw new UnsupportedOperationException();
diff --git
a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
index 2e7188c4480f..38efd35994bb 100644
---
a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
+++
b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
@@ -18,13 +18,10 @@ package org.apache.camel.impl.console;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.function.Function;
import org.apache.camel.Exchange;
-import org.apache.camel.Route;
-import org.apache.camel.api.management.ManagedCamelContext;
-import org.apache.camel.api.management.mbean.ManagedRouteMBean;
+import org.apache.camel.NamedRoute;
import org.apache.camel.spi.ModelDumpLine;
import org.apache.camel.spi.ModelToStructureDumper;
import org.apache.camel.spi.annotations.DevConsole;
@@ -43,8 +40,6 @@ import static
org.apache.camel.impl.console.ConsoleHelper.extractSourceLocationN
@DevConsole(name = "route-structure", description = "Dump route structure")
public class RouteStructureDevConsole extends AbstractDevConsole {
- // TODO: no JMX but model only
-
/**
* Filters the routes matching by route id, route uri, and source location
*/
@@ -69,15 +64,16 @@ public class RouteStructureDevConsole extends
AbstractDevConsole {
final String brief = (String) options.getOrDefault(BRIEF, "false");
final StringBuilder sb = new StringBuilder();
- Function<ManagedRouteMBean, Object> task = mrb -> {
+ Function<NamedRoute, Object> task = def -> {
try {
ModelToStructureDumper dumper =
PluginHelper.getModelToStructureDumper(getCamelContext());
List<ModelDumpLine> lines
- = dumper.dumpStructure(getCamelContext(),
mrb.getRouteId(), "true".equalsIgnoreCase(brief));
+ = dumper.dumpStructure(getCamelContext(),
def.getRouteId(), "true".equalsIgnoreCase(brief));
- sb.append(String.format(" Id: %s", mrb.getRouteId()));
- if (mrb.getSourceLocation() != null) {
- sb.append(String.format("%n Source: %s",
extractSourceLocationNoLineNumber(mrb.getSourceLocation())));
+ sb.append(String.format(" Id: %s", def.getRouteId()));
+ if (def.getResource() != null) {
+ sb.append(String.format("%n Source: %s",
+
extractSourceLocationNoLineNumber(def.getResource().getLocation())));
}
sb.append("\n\n");
for (ModelDumpLine line : lines) {
@@ -108,27 +104,27 @@ public class RouteStructureDevConsole extends
AbstractDevConsole {
final JsonObject root = new JsonObject();
final JsonArray list = new JsonArray();
- Function<ManagedRouteMBean, Object> task = mrb -> {
+ Function<NamedRoute, Object> task = def -> {
JsonObject jo = new JsonObject();
list.add(jo);
- jo.put("routeId", mrb.getRouteId());
- jo.put("from", mrb.getEndpointUri());
- if (mrb.getSourceLocation() != null) {
- jo.put("source",
extractSourceLocationNoLineNumber(mrb.getSourceLocation()));
- Integer line =
extractSourceLocationLineNumber(mrb.getSourceLocation());
+ jo.put("routeId", def.getRouteId());
+ jo.put("from", def.getEndpointUrl());
+ if (def.getResource() != null) {
+ jo.put("source",
extractSourceLocationNoLineNumber(def.getResource().getLocation()));
+ Integer line =
extractSourceLocationLineNumber(def.getResource().getLocation());
if (line != null) {
jo.put("line", line);
}
}
- if (mrb.getDescription() != null) {
- jo.put("description", mrb.getDescription());
+ if (def.getDescription() != null) {
+ jo.put("description", def.getDescription());
}
try {
ModelToStructureDumper dumper =
PluginHelper.getModelToStructureDumper(getCamelContext());
List<ModelDumpLine> lines
- = dumper.dumpStructure(getCamelContext(),
mrb.getRouteId(), "true".equalsIgnoreCase(brief));
+ = dumper.dumpStructure(getCamelContext(),
def.getRouteId(), "true".equalsIgnoreCase(brief));
JsonArray code = dumpAsJSon(lines);
jo.put("code", code);
} catch (Exception e) {
@@ -141,45 +137,36 @@ public class RouteStructureDevConsole extends
AbstractDevConsole {
return root;
}
- protected void doCall(Map<String, Object> options,
Function<ManagedRouteMBean, Object> task) {
+ protected void doCall(Map<String, Object> options, Function<NamedRoute,
Object> task) {
String path = (String) options.get(Exchange.HTTP_PATH);
String subPath = path != null ? StringHelper.after(path, "/") : null;
String filter = (String) options.get(FILTER);
String limit = (String) options.get(LIMIT);
final int max = limit == null ? Integer.MAX_VALUE :
Integer.parseInt(limit);
- ManagedCamelContext mcc =
getCamelContext().getCamelContextExtension().getContextPlugin(ManagedCamelContext.class);
- if (mcc != null) {
- List<Route> routes = getCamelContext().getRoutes();
- routes.sort((o1, o2) ->
o1.getRouteId().compareToIgnoreCase(o2.getRouteId()));
- routes.stream()
- .map(route -> mcc.getManagedRoute(route.getRouteId()))
- .filter(Objects::nonNull)
- .filter(r -> accept(r, filter))
- .filter(r -> accept(r, subPath))
- .sorted(RouteStructureDevConsole::sort)
- .limit(max)
- .forEach(task::apply);
- }
+ var routes = getCamelContext().getNamedRouteDefinitions();
+ routes.sort((o1, o2) ->
o1.getRouteId().compareToIgnoreCase(o2.getRouteId()));
+ routes.stream()
+ .filter(r -> accept(r, filter))
+ .filter(r -> accept(r, subPath))
+ .limit(max)
+ .forEach(task::apply);
}
- private static boolean accept(ManagedRouteMBean mrb, String filter) {
+ private static boolean accept(NamedRoute route, String filter) {
if (filter == null || filter.isBlank()) {
return true;
}
- String onlyName = LoggerHelper.sourceNameOnly(mrb.getSourceLocation());
- return PatternHelper.matchPattern(mrb.getRouteId(), filter)
- || PatternHelper.matchPattern(mrb.getEndpointUri(), filter)
- || PatternHelper.matchPattern(mrb.getSourceLocationShort(),
filter)
+ String uri = route.getInput().getLabel();
+ String loc = LoggerHelper.getLineNumberLoggerName(route);
+ String onlyName = LoggerHelper.sourceNameOnly(loc);
+ return PatternHelper.matchPattern(route.getRouteId(), filter)
+ || PatternHelper.matchPattern(uri, filter)
+ || PatternHelper.matchPattern(loc, filter)
|| PatternHelper.matchPattern(onlyName, filter);
}
- private static int sort(ManagedRouteMBean o1, ManagedRouteMBean o2) {
- // sort by id
- return o1.getRouteId().compareTo(o2.getRouteId());
- }
-
private static JsonArray dumpAsJSon(List<ModelDumpLine> lines) {
JsonArray code = new JsonArray();
int counter = 0;
diff --git
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 8477fd158e1e..c42c04fd7e15 100644
---
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -30,6 +30,7 @@ import org.apache.camel.CamelContext;
import org.apache.camel.Expression;
import org.apache.camel.FailedToStartRouteException;
import org.apache.camel.LoggingLevel;
+import org.apache.camel.NamedRoute;
import org.apache.camel.Predicate;
import org.apache.camel.Processor;
import org.apache.camel.Route;
@@ -429,6 +430,11 @@ public class DefaultCamelContext extends
SimpleCamelContext implements ModelCame
}
}
+ @Override
+ public List<NamedRoute> getNamedRouteDefinitions() {
+ return new ArrayList<>(model.getRouteDefinitions());
+ }
+
@Override
public List<RestDefinition> getRestDefinitions() {
return model.getRestDefinitions();
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
b/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
index 1cf3e282a892..48e37c40e2e5 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
@@ -123,7 +123,24 @@ public final class LoggerHelper {
}
public static String sourceNameOnly(String location) {
- return stripScheme(stripSourceLocationLineNumber(location));
+ int cnt = StringHelper.countChar(location, ':');
+ if (cnt <= 1) {
+ // include pseudo scheme due to extract methods rely on scheme
included
+ location = "file:" + location;
+ }
+ Integer line = extractSourceLocationLineNumber(location);
+ if (line != null) {
+ // remove line number
+ location = extractSourceLocationNoLineNumber(location);
+ // strip scheme so its only the name
+ if (location.contains(":")) {
+ location = stripScheme(location);
+ }
+ return location;
+ } else {
+ // no line number so strip scheme
+ return stripScheme(location);
+ }
}
public static Integer extractSourceLocationLineNumber(String location) {
@@ -143,4 +160,13 @@ public final class LoggerHelper {
return null;
}
+ public static String extractSourceLocationNoLineNumber(String location) {
+ Integer line = extractSourceLocationLineNumber(location);
+ if (line != null) {
+ int pos = location.lastIndexOf(':');
+ return location.substring(0, pos);
+ }
+ return location;
+ }
+
}