Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5134,7 +5134,7 @@
"properties": {
"id": {
"type": "string",
"description": "The processor ID"
"description": "The processor ID (the id of the from for the route input, as in the trace and message history)"
},
"type": {
"type": "string",
Expand Down Expand Up @@ -5175,7 +5175,7 @@
"properties": {
"id": {
"type": "string",
"description": "The processor ID"
"description": "The processor ID (the id of the from for the route input, as in the trace and message history)"
},
"type": {
"type": "string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"properties": {
"id": {
"type": "string",
"description": "The processor ID"
"description": "The processor ID (the id of the from for the route input, as in the trace and message history)"
},
"type": {
"type": "string",
Expand Down Expand Up @@ -83,7 +83,7 @@
"properties": {
"id": {
"type": "string",
"description": "The processor ID"
"description": "The processor ID (the id of the from for the route input, as in the trace and message history)"
},
"type": {
"type": "string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"properties": {
"id": {
"type": "string",
"description": "The processor ID"
"description": "The processor ID (the id of the from for the route input, as in the trace and message history)"
},
"type": {
"type": "string",
Expand Down Expand Up @@ -83,7 +83,7 @@
"properties": {
"id": {
"type": "string",
"description": "The processor ID"
"description": "The processor ID (the id of the from for the route input, as in the trace and message history)"
},
"type": {
"type": "string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public class ProcessorDetailDevConsole extends AbstractDevConsole {
public static final String ROUTE_ID = "routeId";

public record ProcessorEntry(
@Metadata(description = "The processor ID") String id,
@Metadata(description = "The processor ID (the id of the from for the route input, as in the trace and message history)") String id,
@Metadata(description = "The processor type (the XML element name, or 'from' for the route input)") String type,
@Metadata(description = "The endpoint URI (only present for the route input entry)") String endpointUri,
@Metadata(description = "The source line number (only present when known)") Integer line,
Expand Down Expand Up @@ -160,6 +160,8 @@ private static RouteDetail buildRouteDetail(ManagedRouteMBean mr) {
List<ProcessorEntry> processors = new ArrayList<>();

Integer fromLine = null;
// the from has a node id of its own (from1), which the trace and message history name it by
String fromId = routeId;

try {
String xml = mr.dumpRouteAsXml(false, true, true);
Expand All @@ -175,7 +177,11 @@ private static RouteDetail buildRouteDetail(ManagedRouteMBean mr) {
// extract source line number for the from entry from the <from> child element
NodeList fromNodes = routeElement.getElementsByTagName("from");
if (fromNodes.getLength() > 0) {
fromLine = extractSourceLineNumber((Element) fromNodes.item(0));
Element from = (Element) fromNodes.item(0);
fromLine = extractSourceLineNumber(from);
if (!from.getAttribute("id").isEmpty()) {
fromId = from.getAttribute("id");
}
}

collectProcessors(routeElement, processors);
Expand All @@ -184,7 +190,7 @@ private static RouteDetail buildRouteDetail(ManagedRouteMBean mr) {
// ignore
}

ProcessorEntry fromEntry = new ProcessorEntry(routeId, "from", mr.getEndpointUri(), fromLine, new LinkedHashMap<>());
ProcessorEntry fromEntry = new ProcessorEntry(fromId, "from", mr.getEndpointUri(), fromLine, new LinkedHashMap<>());
processors.add(0, fromEntry);

return new RouteDetail(routeId, processors);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.impl.console;

import java.util.Map;

import org.apache.camel.ContextTestSupport;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.console.DevConsole;
import org.apache.camel.model.ModelCamelContext;
import org.apache.camel.support.PluginHelper;
import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
* The route input is named by the id of its from (from1), as the trace and the message history name it, not by the id
* of the route (CAMEL-26864).
*/
class ProcessorDetailFromIdTest extends ContextTestSupport {

@Override
protected boolean useJmx() {
// the processor-detail console reads the routes from JMX
return true;
}

@Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
@Override
public void configure() {
from("direct:start").routeId("myRoute").to("mock:result");
}
};
}

@Test
void theFromIsNamedByItsNodeId() {
DevConsole con = PluginHelper.getDevConsoleResolver(context).resolveDevConsole("processor-detail");
JsonObject out = (JsonObject) con.call(DevConsole.MediaType.JSON, Map.of("routeId", "myRoute"));

JsonObject from = (JsonObject) ((JsonArray) out.get("processors")).get(0);
String fromId = ((ModelCamelContext) context).getRouteDefinition("myRoute").getInput().getId();
Assertions.assertEquals("from", from.getString("type"));
Assertions.assertNotNull(fromId);
Assertions.assertEquals(fromId, from.getString("id"));
Assertions.assertNotEquals("myRoute", from.getString("id"));
Assertions.assertEquals("myRoute", out.getString("routeId"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@ new `reply` component; its seven-argument constructor is kept and creates an edg
A `wireTap` or a `toD` to an endpoint the route names, rather than one it computes with an expression, is now an edge
too (a wire tap never waits for the answer), and an external endpoint when no route consumes from it.

=== camel-console - the processor-detail console names the route input by the id of its from

The first entry of the `processor-detail` developer console, the route input (`type` is `from`), now has the id of the
`from` of the route as `id` (such as `from1`, or the id given to the `from`), which the tracer, the message history and
the backlog debugger name it by. It had the route id before, which is still the `routeId` of the response.

=== camel-management - LastExchangeCompletedExchangeId is updated at most once per millisecond

The JMX attribute `LastExchangeCompletedExchangeId`, of the `CamelContext`, route and processor MBeans, is now updated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.camel.diagram.RouteDiagramLayoutEngine;
import org.apache.camel.dsl.jbang.core.commands.tui.diagram.DiagramColors;
import org.apache.camel.util.TimeUtils;
import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;

import static org.apache.camel.dsl.jbang.core.commands.tui.EipDocSupport.*;
Expand Down Expand Up @@ -133,6 +134,10 @@ private JsonObject requestRouteProcessorDetail(String routeId) {
}
}

void setRouteDetailForTesting(JsonObject routeDetail) {
cachedRouteDetail = routeDetail;
}

JsonObject findProcessorEntry(String nodeId) {
if (cachedRouteDetail == null || nodeId == null) {
return null;
Expand All @@ -142,6 +147,16 @@ JsonObject findProcessorEntry(String nodeId) {
return p;
}
}
// the diagram names the input of a route by the route id, the app by the id of its from (from1)
JsonArray routes = (JsonArray) cachedRouteDetail.get("routes");
for (Object r : routes != null ? routes : List.of()) {
JsonObject route = (JsonObject) r;
JsonArray procs = (JsonArray) route.get("processors");
if (nodeId.equals(route.getString("routeId")) && procs != null && !procs.isEmpty()
&& "from".equals(((JsonObject) procs.get(0)).getString("type"))) {
return (JsonObject) procs.get(0);
}
}
return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.dsl.jbang.core.commands.tui;

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.camel.util.json.JsonObject;
import org.apache.camel.util.json.Jsoner;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* CAMEL-26864: the app names the input of a route by the id of its from (from1), as the trace does; the diagram names
* it by the route id. The detail panel finds it by either, and by the route id with an app that still says so.
*/
class DiagramDetailFromIdTest {

@Test
void theFromIsFoundByItsIdAndByTheRouteId() throws Exception {
MonitorContext ctx = new MonitorContext(new AtomicReference<>(List.of()), new AtomicReference<>(List.of()));
DiagramDetailSupport detail = new DiagramDetailSupport(ctx, new DiagramSupport());
detail.setRouteDetailForTesting((JsonObject) Jsoner.deserialize("""
{"routes": [
{"routeId": "hello", "processors": [
{"id": "from1", "type": "from", "endpointUri": "timer://tick"},
{"id": "setBody1", "type": "setBody"}]},
{"routeId": "seven", "processors": [
{"id": "seven", "type": "from", "endpointUri": "direct://seven"}]}]}
"""));

assertThat(detail.findProcessorEntry("from1").getString("endpointUri")).isEqualTo("timer://tick");
assertThat(detail.findProcessorEntry("hello").getString("endpointUri")).as("the diagram's from node")
.isEqualTo("timer://tick");
assertThat(detail.findProcessorEntry("setBody1").getString("type")).isEqualTo("setBody");
assertThat(detail.findProcessorEntry("seven").getString("endpointUri")).as("an app before CAMEL-26864")
.isEqualTo("direct://seven");
assertThat(detail.findProcessorEntry("nope")).isNull();
}
}
Loading