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 b21e782 CAMEL-17400: Enrich route model with source location:line for
JVM programming language, Java, Kotlin, Groovy etc.
b21e782 is described below
commit b21e7829bbdf5adc6d6563d86c838650cd90f5d2
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Jan 1 11:02:06 2022 +0100
CAMEL-17400: Enrich route model with source location:line for JVM
programming language, Java, Kotlin, Groovy etc.
---
.../java/org/apache/camel/LineNumberAware.java | 10 +++++++
.../org/apache/camel/builder/RouteBuilder.java | 8 +++---
.../camel/model/OptionalIdentifiedDefinition.java | 29 +++++++++++++++++++-
.../apache/camel/model/ProcessorDefinition.java | 21 +++++++++++++-
.../camel/model/ProcessorDefinitionHelper.java | 27 ++++++++++++++++++
.../org/apache/camel/model/RouteDefinition.java | 12 +++++++-
.../org/apache/camel/model/RoutesDefinition.java | 1 +
.../camel/main/DefaultConfigurationProperties.java | 10 +++++++
.../management/mbean/ManagedCamelContext.java | 11 ++++++--
.../camel/management/mbean/ManagedProcessor.java | 7 +++--
.../camel/management/mbean/ManagedRoute.java | 2 +-
.../camel/management/ManagedCamelContextTest.java | 32 ++++++++++++++++++++--
12 files changed, 155 insertions(+), 15 deletions(-)
diff --git a/core/camel-api/src/main/java/org/apache/camel/LineNumberAware.java
b/core/camel-api/src/main/java/org/apache/camel/LineNumberAware.java
index fa9f299..941b3e5 100644
--- a/core/camel-api/src/main/java/org/apache/camel/LineNumberAware.java
+++ b/core/camel-api/src/main/java/org/apache/camel/LineNumberAware.java
@@ -36,4 +36,14 @@ public interface LineNumberAware {
*/
void setLineNumber(int lineNumber);
+ /**
+ * The location of the entity.
+ */
+ String getLocation();
+
+ /**
+ * Sets the location of the entity (such as classname, XML file name, etc.)
+ */
+ void setLocation(String location);
+
}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
index f3ae520..b1a760e 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
@@ -746,18 +746,18 @@ public abstract class RouteBuilder extends BuilderSupport
implements RoutesBuild
}
protected void configureRest(RestDefinition rest) {
- // noop
+ CamelContextAware.trySetCamelContext(rest, getContext());
}
protected void configureRoute(RouteDefinition route) {
- // noop
+ CamelContextAware.trySetCamelContext(route, getContext());
}
protected void configureRouteTemplate(RouteTemplateDefinition
routeTemplate) {
- // noop
+ CamelContextAware.trySetCamelContext(routeTemplate, getContext());
}
protected void configureRouteConfiguration(RouteConfigurationDefinition
routesConfiguration) {
- // noop
+ CamelContextAware.trySetCamelContext(routesConfiguration,
getContext());
}
}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java
index ade87e3..c36cc11 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java
@@ -23,6 +23,8 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
import org.apache.camel.NamedNode;
import org.apache.camel.spi.IdAware;
import org.apache.camel.spi.Metadata;
@@ -34,12 +36,26 @@ import org.apache.camel.spi.NodeIdFactory;
@XmlType(name = "optionalIdentifiedDefinition")
@XmlAccessorType(XmlAccessType.PROPERTY)
// must use XmlAccessType.PROPERTY which is required by camel-spring /
camel-blueprint for their namespace parsers
-public abstract class OptionalIdentifiedDefinition<T extends
OptionalIdentifiedDefinition<T>> implements NamedNode, IdAware {
+public abstract class OptionalIdentifiedDefinition<T extends
OptionalIdentifiedDefinition<T>>
+ implements NamedNode, IdAware, CamelContextAware {
+ private CamelContext camelContext;
private String id;
private Boolean customId;
private DescriptionDefinition description;
private transient int lineNumber = -1;
+ private transient String location;
+
+ @Override
+ public CamelContext getCamelContext() {
+ return camelContext;
+ }
+
+ @Override
+ @XmlTransient
+ public void setCamelContext(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
@Override
public String getId() {
@@ -93,6 +109,17 @@ public abstract class OptionalIdentifiedDefinition<T
extends OptionalIdentifiedD
this.lineNumber = lineNumber;
}
+ @Override
+ public String getLocation() {
+ return location;
+ }
+
+ @Override
+ @XmlTransient
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
// Fluent API
//
-------------------------------------------------------------------------
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index 60d3bfb..1dd3fa8 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -35,6 +35,8 @@ import javax.xml.bind.annotation.XmlTransient;
import org.apache.camel.AggregationStrategy;
import org.apache.camel.BeanScope;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
@@ -90,7 +92,7 @@ public abstract class ProcessorDefinition<Type extends
ProcessorDefinition<Type>
private final int index;
protected ProcessorDefinition() {
- // every time we create a definition we should inc the COUNTER counter
+ // every time we create a definition we should inc the counter
index = COUNTER.getAndIncrement();
}
@@ -160,6 +162,23 @@ public abstract class ProcessorDefinition<Type extends
ProcessorDefinition<Type>
@Override
public void addOutput(ProcessorDefinition<?> output) {
+ // inject context
+ CamelContextAware.trySetCamelContext(output, getCamelContext());
+
+ RouteDefinition route = ProcessorDefinitionHelper.getRoute(this);
+ if (route != null) {
+ CamelContext context = route.getCamelContext();
+ if (context != null && context.isDebugging()) {
+ // we want to capture source location:line for every output
when debugging is enabled
+ // this is an expensive operation and therefore only used if
debugging is enabled
+ ProcessorDefinitionHelper.prepareSourceLocation(output);
+ if (log.isDebugEnabled()) {
+ log.debug("{} located in {}:{}", output.getShortName(),
output.getLocation(),
+ output.getLineNumber());
+ }
+ }
+ }
+
if (!(this instanceof OutputNode)) {
getParent().addOutput(output);
return;
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
index 3245035..2551451 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
@@ -370,4 +370,31 @@ public final class ProcessorDefinitionHelper {
}
}
+ /**
+ * Prepares the output to gather source location:line-number if possible.
This operation is slow as it uses
+ * StackTrace so this should only be used when Camel Debugger is enabled.
+ *
+ * @param node the node
+ */
+ public static void prepareSourceLocation(NamedNode node) {
+ // line number may already be set if parsed via XML, YAML etc.
+ int number = node.getLineNumber();
+ if (number < 0) {
+ StackTraceElement[] st = Thread.currentThread().getStackTrace();
+ // skip first stack as that is this method
+ for (int i = 1; i < st.length; i++) {
+ StackTraceElement e = st[i];
+ if (!e.getClassName().startsWith("org.apache.camel.model") &&
+
!e.getClassName().startsWith("org.apache.camel.builder.RouteBuilder")) {
+ // when we are no longer in model/RouteBuilder, we have
found the location:line-number
+ node.setLineNumber(e.getLineNumber());
+ if (node.getLocation() == null) {
+ node.setLocation(e.getClassName());
+ }
+ return;
+ }
+ }
+ }
+ }
+
}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
index 91c7b66..f318336 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -729,8 +729,18 @@ public class RouteDefinition extends
OutputDefinition<RouteDefinition> implement
throw new IllegalArgumentException("Only one input is allowed per
route. Cannot accept input: " + input);
}
// required = false: in rest-dsl you can embed an in-lined route which
- // does not have a <from> as its implied to be the rest endpoint
+ // does not have a <from> as it is implied to be the rest endpoint
this.input = input;
+
+ if (getCamelContext() != null && getCamelContext().isDebugging()) {
+ // we want to capture source location:line for every output when
debugging is enabled
+ // this is an expensive operation and therefore only used if
debugging is enabled
+ ProcessorDefinitionHelper.prepareSourceLocation(input);
+ if (log.isDebugEnabled()) {
+ log.debug("{} located in {}:{}", input.getShortName(),
input.getLocation(),
+ input.getLineNumber());
+ }
+ }
}
@Override
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index fce66a6..1ef0a31 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -364,6 +364,7 @@ public class RoutesDefinition extends
OptionalIdentifiedDefinition<RoutesDefinit
//
-------------------------------------------------------------------------
protected RouteDefinition createRoute() {
RouteDefinition route = new RouteDefinition();
+ route.setCamelContext(getCamelContext());
ErrorHandlerFactory handler = getErrorHandlerFactory();
if (handler != null) {
route.setErrorHandlerFactoryIfNull(handler);
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 53ed817..0b6e0b2 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
@@ -1978,6 +1978,16 @@ public abstract class DefaultConfigurationProperties<T> {
}
/**
+ * Sets whether debugging is enabled or not.
+ *
+ * Default is false.
+ */
+ public T withDebugging(boolean debugging) {
+ this.debugging = debugging;
+ return (T) this;
+ }
+
+ /**
* Sets the pattern used for determine which custom MDC keys to propagate
during message routing when the routing
* engine continues routing asynchronously for the given message. Setting
this pattern to * will propagate all
* custom keys. Or setting the pattern to foo*,bar* will propagate any
keys starting with either foo or bar. Notice
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 3ec68aa..94fc7b5 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
@@ -657,7 +657,11 @@ public class ManagedCamelContext extends
ManagedPerformanceCounter implements Ti
if (rd != null) {
String id = rd.getRouteId();
int line = rd.getInput().getLineNumber();
- String location = route.getSourceLocation() != null ?
route.getSourceLocation() : "";
+ String location
+ = rd.getInput().getLocation() != null ?
rd.getInput().getLocation() : route.getSourceLocation();
+ if (location == null) {
+ location = "";
+ }
sb.append("\n <routeLocation")
.append(String.format(
" routeId=\"%s\" id=\"%s\" index=\"%s\"
sourceLocation=\"%s\" sourceLineNumber=\"%s\"/>",
@@ -667,7 +671,10 @@ public class ManagedCamelContext extends
ManagedPerformanceCounter implements Ti
// the step must belong to this route
if (route.getRouteId().equals(processor.getRouteId())) {
int line = processor.getSourceLineNumber() != null ?
processor.getSourceLineNumber() : -1;
- String location = route.getSourceLocation() != null ?
route.getSourceLocation() : "";
+ String location = processor.getSourceLocation();
+ if (location == null) {
+ location = "";
+ }
sb.append("\n <routeLocation")
.append(String.format(
" routeId=\"%s\" id=\"%s\"
index=\"%s\" sourceLocation=\"%s\" sourceLineNumber=\"%s\"/>",
diff --git
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedProcessor.java
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedProcessor.java
index 1acfe0d..ba06da2 100644
---
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedProcessor.java
+++
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedProcessor.java
@@ -56,9 +56,10 @@ public class ManagedProcessor extends
ManagedPerformanceCounter implements Manag
step =
ProcessorDefinitionHelper.findFirstParentOfType(StepDefinition.class,
definition, true);
}
this.stepId = step != null ?
step.idOrCreate(context.adapt(ExtendedCamelContext.class).getNodeIdFactory()) :
null;
- RouteDefinition rd = ProcessorDefinitionHelper.getRoute(definition);
- if (rd != null && rd.getResource() != null) {
- this.sourceLocation = rd.getResource().getLocation();
+ this.sourceLocation = definition.getLocation();
+ if (sourceLocation == null) {
+ RouteDefinition rd =
ProcessorDefinitionHelper.getRoute(definition);
+ sourceLocation = rd != null ? rd.getLocation() : null;
}
}
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 7861aa8..8b38164 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
@@ -571,7 +571,7 @@ public class ManagedRoute extends ManagedPerformanceCounter
implements TimerList
// the step must belong to this route
if (route.getRouteId().equals(processor.getRouteId())) {
int line = processor.getSourceLineNumber() != null ?
processor.getSourceLineNumber() : -1;
- String location = getSourceLocation() != null ?
getSourceLocation() : "";
+ String location = processor.getSourceLocation() != null ?
processor.getSourceLocation() : "";
sb.append("\n <routeLocation")
.append(String.format(
" routeId=\"%s\" id=\"%s\" index=\"%s\"
sourceLocation=\"%s\" sourceLineNumber=\"%s\"/>",
diff --git
a/core/camel-management/src/test/java/org/apache/camel/management/ManagedCamelContextTest.java
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedCamelContextTest.java
index 457d2d0..53be4fd 100644
---
a/core/camel-management/src/test/java/org/apache/camel/management/ManagedCamelContextTest.java
+++
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedCamelContextTest.java
@@ -52,6 +52,8 @@ public class ManagedCamelContextTest extends
ManagementTestSupport {
// to force a different management name than the camel id
context.getManagementNameStrategy().setNamePattern("19-#name#");
context.setNameStrategy(new
ExplicitCamelContextNameStrategy("my-camel-context"));
+ // debugger needed for source locations
+ context.setDebugging(true);
return context;
}
@@ -253,14 +255,40 @@ public class ManagedCamelContextTest extends
ManagementTestSupport {
Assertions.assertTrue(names.contains("reverse"));
}
+ @Test
+ public void testSourceLocations() throws Exception {
+ MBeanServer mbeanServer = getMBeanServer();
+ ObjectName on = getContextObjectName();
+
+ String xml = (String) mbeanServer.invoke(on,
"dumpRoutesSourceLocationsAsXml", null, null);
+ Assertions.assertNotNull(xml);
+ Assertions.assertTrue(xml.contains(
+
"sourceLocation=\"org.apache.camel.management.ManagedCamelContextTest$1\"
sourceLineNumber=\"285\"/>"));
+ Assertions.assertTrue(xml.contains(
+
"sourceLocation=\"org.apache.camel.management.ManagedCamelContextTest$1\"
sourceLineNumber=\"286\"/>"));
+ Assertions.assertTrue(xml.contains(
+
"sourceLocation=\"org.apache.camel.management.ManagedCamelContextTest$1\"
sourceLineNumber=\"287\"/>"));
+
+ Assertions.assertTrue(xml.contains(
+
"sourceLocation=\"org.apache.camel.management.ManagedCamelContextTest$1\"
sourceLineNumber=\"289\"/>"));
+ Assertions.assertTrue(xml.contains(
+
"sourceLocation=\"org.apache.camel.management.ManagedCamelContextTest$1\"
sourceLineNumber=\"290\"/>"));
+ Assertions.assertTrue(xml.contains(
+
"sourceLocation=\"org.apache.camel.management.ManagedCamelContextTest$1\"
sourceLineNumber=\"291\"/>"));
+ }
+
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
- from("direct:start").delay(10).to("mock:result");
+ from("direct:start")
+ .delay(10)
+ .to("mock:result");
- from("direct:foo").delay(10).transform(constant("Bye
World")).id("myTransform");
+ from("direct:foo")
+ .delay(10)
+ .transform(constant("Bye World")).id("myTransform");
}
};
}