You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/12/21 14:38:56 UTC

(camel) branch jmx-upd created (now 19fd2607e2e)

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a change to branch jmx-upd
in repository https://gitbox.apache.org/repos/asf/camel.git


      at 19fd2607e2e Regen

This branch includes the following new commits:

     new acd9a0b5f37 CAMEL-20274: camel-management - Add JMX operation to update route from XML
     new 68b21fe063d CAMEL-20274: camel-management - Add JMX operation to update route from XML
     new dbb71d02ca2 CAMEL-20274: camel-management - Add JMX operation to update route from XML
     new 19fd2607e2e Regen

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(camel) 01/04: CAMEL-20274: camel-management - Add JMX operation to update route from XML

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch jmx-upd
in repository https://gitbox.apache.org/repos/asf/camel.git

commit acd9a0b5f37d60c9467c3a3138e2004e8495a310
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Dec 21 15:07:36 2023 +0100

    CAMEL-20274: camel-management - Add JMX operation to update route from XML
---
 .../main/java/org/apache/camel/CamelContext.java   |   1 +
 .../java/org/apache/camel/clock/ContextClock.java  |  15 +-
 .../java/org/apache/camel/clock/EventClock.java    |   7 +-
 .../camel/impl/engine/AbstractCamelContext.java    |   1 -
 .../api/management/mbean/ManagedRouteMBean.java    |   4 +
 core/camel-management/pom.xml                      |   4 +
 .../camel/management/mbean/ManagedRoute.java       |  38 +++++
 .../camel/management/ManagedFromRestGetTest.java   |  10 +-
 .../management/ManagedFromRestPlaceholderTest.java |  10 +-
 .../ManagedRouteUpdateRouteFromXmlTest.java        | 153 +++++++++++++++++++++
 10 files changed, 224 insertions(+), 19 deletions(-)

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 1035141046d..22cfc3ed793 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
@@ -185,6 +185,7 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
 
     /**
      * Gets a clock instance that keeps track of time for relevant CamelContext events
+     *
      * @return A clock instance
      */
     EventClock<ContextEvents> getClock();
diff --git a/core/camel-api/src/main/java/org/apache/camel/clock/ContextClock.java b/core/camel-api/src/main/java/org/apache/camel/clock/ContextClock.java
index 2bc575a0abf..edc6ae65a19 100644
--- a/core/camel-api/src/main/java/org/apache/camel/clock/ContextClock.java
+++ b/core/camel-api/src/main/java/org/apache/camel/clock/ContextClock.java
@@ -50,9 +50,10 @@ public final class ContextClock implements EventClock<ContextEvents> {
 
     /**
      * Get the elapsed time for the event
-     * @param event the event to get the elapsed time
-     * @param defaultValue the default value to provide if the event is not being tracked
-     * @return The elapsed time or the default value if the event is not being tracked
+     *
+     * @param  event        the event to get the elapsed time
+     * @param  defaultValue the default value to provide if the event is not being tracked
+     * @return              The elapsed time or the default value if the event is not being tracked
      */
     public long elapsed(ContextEvents event, long defaultValue) {
         Clock clock = events.get(event);
@@ -65,9 +66,11 @@ public final class ContextClock implements EventClock<ContextEvents> {
 
     /**
      * Get the time for the event as a Date object
-     * @param event the event to get the elapsed time
-     * @param defaultValue the default value to provide if the event is not being tracked
-     * @return The Date object representing the creation date or the default value if the event is not being tracked
+     *
+     * @param  event        the event to get the elapsed time
+     * @param  defaultValue the default value to provide if the event is not being tracked
+     * @return              The Date object representing the creation date or the default value if the event is not
+     *                      being tracked
      */
     public Date asDate(ContextEvents event, Date defaultValue) {
         Clock clock = events.get(event);
diff --git a/core/camel-api/src/main/java/org/apache/camel/clock/EventClock.java b/core/camel-api/src/main/java/org/apache/camel/clock/EventClock.java
index 924640a5814..18136904229 100644
--- a/core/camel-api/src/main/java/org/apache/camel/clock/EventClock.java
+++ b/core/camel-api/src/main/java/org/apache/camel/clock/EventClock.java
@@ -19,12 +19,14 @@ package org.apache.camel.clock;
 
 /**
  * A specialized clock that tracks the pass of time for one or more types of events
+ *
  * @param <T> The event type as an Enum
  */
 public interface EventClock<T extends Enum<T>> extends Clock {
 
     /**
      * Add the event to be tracked
+     *
      * @param event the event to track
      * @param clock the clock associated with the event
      */
@@ -32,8 +34,9 @@ public interface EventClock<T extends Enum<T>> extends Clock {
 
     /**
      * Get the clock for the event
-     * @param event the event to get the clock for
-     * @return the clock instance or null if not set
+     *
+     * @param  event the event to get the clock for
+     * @return       the clock instance or null if not set
      */
     Clock get(T event);
 }
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 49b5d5bb0d5..5f2060182d7 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
@@ -72,7 +72,6 @@ import org.apache.camel.TypeConverter;
 import org.apache.camel.VetoCamelContextStartException;
 import org.apache.camel.api.management.JmxSystemPropertyKeys;
 import org.apache.camel.catalog.RuntimeCamelCatalog;
-import org.apache.camel.clock.Clock;
 import org.apache.camel.clock.ContextClock;
 import org.apache.camel.clock.EventClock;
 import org.apache.camel.console.DevConsoleRegistry;
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 9687add7998..4adb688971d 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
@@ -165,4 +165,8 @@ public interface ManagedRouteMBean extends ManagedPerformanceCounterMBean {
 
     @ManagedOperation(description = "IDs for the processors that are part of this route")
     Collection<String> processorIds() throws Exception;
+
+    @ManagedOperation(description = "Updates the route from XML")
+    void updateRouteFromXml(String xml) throws Exception;
+
 }
diff --git a/core/camel-management/pom.xml b/core/camel-management/pom.xml
index 1a9adec3710..72e2dbc7ee3 100644
--- a/core/camel-management/pom.xml
+++ b/core/camel-management/pom.xml
@@ -47,6 +47,10 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-core-engine</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-xml-jaxb</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-bean</artifactId>
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 d3c559e5198..0bd96f85748 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
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.management.mbean;
 
+import java.io.InputStream;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -41,6 +42,7 @@ import javax.management.openmbean.TabularData;
 import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.ManagementStatisticsLevel;
 import org.apache.camel.Route;
 import org.apache.camel.RuntimeCamelException;
@@ -55,11 +57,13 @@ import org.apache.camel.api.management.mbean.RouteError;
 import org.apache.camel.model.Model;
 import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.spi.InflightRepository;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.spi.RoutePolicy;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.xml.jaxb.JaxbHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -672,6 +676,40 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
         }
     }
 
+    @Override
+    public void updateRouteFromXml(String xml) throws Exception {
+        // convert to model from xml
+        ExtendedCamelContext ecc = context.getCamelContextExtension();
+        InputStream is = context.getTypeConverter().convertTo(InputStream.class, xml);
+        RoutesDefinition routes = JaxbHelper.loadRoutesDefinition(context, is);
+        if (routes == null || routes.getRoutes().isEmpty()) {
+            return;
+        }
+        RouteDefinition def = routes.getRoutes().get(0);
+
+        // if the xml does not contain the route-id then we fix this by adding the actual route id
+        // this may be needed if the route-id was auto-generated, as the intend is to update this route
+        // and not add a new route, adding a new route, use the MBean operation on ManagedCamelContext instead.
+        if (ObjectHelper.isEmpty(def.getId())) {
+            def.setId(getRouteId());
+        } else if (!def.getId().equals(getRouteId())) {
+            throw new IllegalArgumentException(
+                    "Cannot update route from XML as routeIds does not match. routeId: "
+                                               + getRouteId() + ", routeId from XML: " + def.getId());
+        }
+
+        LOG.debug("Updating route: {} from xml: {}", def.getId(), xml);
+        try {
+            // add will remove existing route first
+            ecc.getContextPlugin(Model.class).addRouteDefinition(def);
+        } catch (Exception e) {
+            // log the error as warn as the management api may be invoked remotely over JMX which does not propagate such exception
+            String msg = "Error updating route: " + def.getId() + " from xml: " + xml + " due: " + e.getMessage();
+            LOG.warn(msg, e);
+            throw e;
+        }
+    }
+
     @Override
     public boolean equals(Object o) {
         return this == o || o != null && getClass() == o.getClass() && route.equals(((ManagedRoute) o).route);
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestGetTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestGetTest.java
index 086719e7c02..c4e1df5bd7c 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestGetTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestGetTest.java
@@ -64,14 +64,14 @@ public class ManagedFromRestGetTest extends ManagementTestSupport {
         assertTrue(xml.contains("application/json"));
         assertTrue(xml.contains("</rests>"));
 
-        assertTrue(xml.contains("<param defaultValue=\"1\" dataType=\"integer\" name=\"header_count\""
-                                + " description=\"header param description1\" type=\"header\" required=\"true\">"));
-        assertTrue(xml.contains("<param defaultValue=\"b\" dataType=\"string\" name=\"header_letter\""
-                                + " description=\"header param description2\" type=\"query\" collectionFormat=\"multi\" required=\"false\">"));
+        assertTrue(xml.contains(
+                "<param dataType=\"integer\" defaultValue=\"1\" description=\"header param description1\" name=\"header_count\" required=\"true\" type=\"header\">"));
+        assertTrue(xml.contains(
+                "<param collectionFormat=\"multi\" dataType=\"string\" defaultValue=\"b\" description=\"header param description2\" name=\"header_letter\" required=\"false\" type=\"query\">"));
         assertTrue(xml.contains("<value>1</value>"));
         assertTrue(xml.contains("<value>a</value>"));
 
-        assertTrue(xml.contains("<responseMessage code=\"300\" responseModel=\"java.lang.Integer\" message=\"test msg\"/>"));
+        assertTrue(xml.contains("<responseMessage code=\"300\" message=\"test msg\" responseModel=\"java.lang.Integer\"/>"));
 
         String xml2 = (String) mbeanServer.invoke(on, "dumpRoutesAsXml", null, null);
         log.info(xml2);
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java
index 7984b258693..c09629efc86 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java
@@ -65,14 +65,14 @@ public class ManagedFromRestPlaceholderTest extends ManagementTestSupport {
         assertTrue(xml.contains("application/json"));
         assertTrue(xml.contains("</rests>"));
 
-        assertTrue(xml.contains("<param defaultValue=\"1\" dataType=\"integer\" name=\"header_count\""
-                                + " description=\"header param description1\" type=\"header\" required=\"true\">"));
-        assertTrue(xml.contains("<param defaultValue=\"b\" dataType=\"string\" name=\"header_letter\""
-                                + " description=\"header param description2\" type=\"query\" collectionFormat=\"multi\" required=\"false\">"));
+        assertTrue(xml.contains(
+                "<param dataType=\"integer\" defaultValue=\"1\" description=\"header param description1\" name=\"header_count\" required=\"true\" type=\"header\">"));
+        assertTrue(xml.contains(
+                "<param collectionFormat=\"multi\" dataType=\"string\" defaultValue=\"b\" description=\"header param description2\" name=\"header_letter\" required=\"false\" type=\"query\">"));
         assertTrue(xml.contains("<value>1</value>"));
         assertTrue(xml.contains("<value>a</value>"));
 
-        assertTrue(xml.contains("<responseMessage code=\"300\" responseModel=\"java.lang.Integer\" message=\"test msg\"/>"));
+        assertTrue(xml.contains("<responseMessage code=\"300\" message=\"test msg\" responseModel=\"java.lang.Integer\"/>"));
 
         String xml2 = (String) mbeanServer.invoke(on, "dumpRoutesAsXml", null, null);
         log.info(xml2);
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteUpdateRouteFromXmlTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteUpdateRouteFromXmlTest.java
new file mode 100644
index 00000000000..7ba41bffef7
--- /dev/null
+++ b/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteUpdateRouteFromXmlTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.management;
+
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+@DisabledOnOs(OS.AIX)
+public class ManagedRouteUpdateRouteFromXmlTest extends ManagementTestSupport {
+
+    @Test
+    public void testUpdateRouteFromXml() throws Exception {
+        MBeanServer mbeanServer = getMBeanServer();
+        ObjectName on = getRouteObjectName(mbeanServer);
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // should be started
+        String routeId = (String) mbeanServer.getAttribute(on, "RouteId");
+        assertEquals("myRoute", routeId);
+
+        String xml = "<route id=\"myRoute\" xmlns=\"http://camel.apache.org/schema/spring\">"
+                     + "  <from uri=\"direct:start\"/>"
+                     + "  <log message=\"This is a changed route saying ${body}\"/>"
+                     + "  <to uri=\"mock:changed\"/>"
+                     + "</route>";
+
+        mbeanServer.invoke(on, "updateRouteFromXml", new Object[] { xml }, new String[] { "java.lang.String" });
+
+        assertEquals(1, context.getRoutes().size());
+
+        getMockEndpoint("mock:changed").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testUpdateRouteFromXmlWithoutRouteId() throws Exception {
+        MBeanServer mbeanServer = getMBeanServer();
+        ObjectName on = getRouteObjectName(mbeanServer);
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // should be started
+        String routeId = (String) mbeanServer.getAttribute(on, "RouteId");
+        assertEquals("myRoute", routeId);
+
+        String xml = "<route xmlns=\"http://camel.apache.org/schema/spring\">"
+                     + "  <from uri=\"direct:start\"/>"
+                     + "  <log message=\"This is a changed route saying ${body}\"/>"
+                     + "  <to uri=\"mock:changed\"/>"
+                     + "</route>";
+
+        mbeanServer.invoke(on, "updateRouteFromXml", new Object[] { xml }, new String[] { "java.lang.String" });
+
+        assertEquals(1, context.getRoutes().size());
+
+        getMockEndpoint("mock:changed").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testUpdateRouteFromXmlMismatchRouteId() throws Exception {
+        MBeanServer mbeanServer = getMBeanServer();
+        ObjectName on = getRouteObjectName(mbeanServer);
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // should be started
+        String routeId = (String) mbeanServer.getAttribute(on, "RouteId");
+        assertEquals("myRoute", routeId);
+
+        String xml = "<route id=\"foo\" xmlns=\"http://camel.apache.org/schema/spring\">"
+                     + "  <from uri=\"direct:start\"/>"
+                     + "  <log message=\"This is a changed route saying ${body}\"/>"
+                     + "  <to uri=\"mock:changed\"/>"
+                     + "</route>";
+
+        try {
+            mbeanServer.invoke(on, "updateRouteFromXml", new Object[] { xml }, new String[] { "java.lang.String" });
+            fail("Should have thrown exception");
+        } catch (Exception e) {
+            assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertEquals("Cannot update route from XML as routeIds does not match. routeId: myRoute, routeId from XML: foo",
+                    e.getCause().getMessage());
+        }
+    }
+
+    static ObjectName getRouteObjectName(MBeanServer mbeanServer) throws Exception {
+        Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null);
+        assertEquals(1, set.size());
+
+        return set.iterator().next();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").routeId("myRoute")
+                        .log("Got ${body}")
+                        .to("mock:result");
+            }
+        };
+    }
+
+}


(camel) 04/04: Regen

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch jmx-upd
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 19fd2607e2ee9fd7cd203dc0f8e8b2bf95045259
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Dec 21 15:38:43 2023 +0100

    Regen
---
 .../org/apache/camel/catalog/components/aws-cloudtrail.json         | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-cloudtrail.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-cloudtrail.json
index 365616cb18a..6b472daa954 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-cloudtrail.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-cloudtrail.json
@@ -43,12 +43,6 @@
     "useDefaultCredentialsProvider": { "index": 18, "kind": "property", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws.cloudtrail.CloudtrailConfiguration", "configurationField": "configuration", "description": "Set whether the Cloudtrail client shoul [...]
     "useProfileCredentialsProvider": { "index": 19, "kind": "property", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws.cloudtrail.CloudtrailConfiguration", "configurationField": "configuration", "description": "Set whether the Cloudtrail client shoul [...]
   },
-  "headers": {
-    "CamelAwsCloudTrailEventId": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The event ID of the cloud trail event consumed.", "constantName": "org.apache.camel.component.aws.cloudtrail.CloudtrailConstants#EVENT_ID" },
-    "CamelAwsCloudTrailEventName": { "index": 1, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The event Name of the cloud trail event consumed.", "constantName": "org.apache.camel.component.aws.cloudtrail.CloudtrailConstants#EVENT_NAME" },
-    "CamelAwsCloudTrailEventSource": { "index": 2, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The event Source of the cloud trail event consumed.", "constantName": "org.apache.camel.component.aws.cloudtrail.CloudtrailConstants#EVENT_SOURCE" },
-    "CamelAwsCloudTrailEventUsername": { "index": 3, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The associated username of the event of the cloud trail event consumed.", "constantName": "org.apache.camel.component.aws.cloudtrail.CloudtrailConstants#USERNAME" }
-  },
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws.cloudtrail.CloudtrailConfiguration", "configurationField": "configuration", "description": "A label for indexing cloudtrail endpoints" },
     "eventSource": { "index": 1, "kind": "parameter", "displayName": "Event Source", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws.cloudtrail.CloudtrailConfiguration", "configurationField": "configuration", "description": "Specify an event source to select events" },


(camel) 03/04: CAMEL-20274: camel-management - Add JMX operation to update route from XML

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch jmx-upd
in repository https://gitbox.apache.org/repos/asf/camel.git

commit dbb71d02ca23ab1bebbb96966756cd361f4e75f4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Dec 21 15:38:38 2023 +0100

    CAMEL-20274: camel-management - Add JMX operation to update route from XML
---
 docs/user-manual/modules/ROOT/pages/jmx.adoc | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/docs/user-manual/modules/ROOT/pages/jmx.adoc b/docs/user-manual/modules/ROOT/pages/jmx.adoc
index ee11faea5a0..d428877efa6 100644
--- a/docs/user-manual/modules/ROOT/pages/jmx.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jmx.adoc
@@ -115,6 +115,10 @@ usage of each incoming and outgoing endpoints).
 |`mask` |`org.apache.camel.jmx.mask` |`true`
 |A flag that indicates whether to remove detected sensitive information (such as passwords)
 from MBean names and attributes.
+
+|`updateRouteEnabled` |`org.apache.camel.jmx.updateRouteEnabled` |`false`
+|Whether to allow updating routes at runtime via JMX using the ManagedRouteMBean. This is disabled by default, but can be enabled for development and troubleshooting purposes, such as updating routes in an existing running Camel via JMX and other tools.
+
 |=======================================================================
 
 === Registering MBeans for specific resources only


(camel) 02/04: CAMEL-20274: camel-management - Add JMX operation to update route from XML

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch jmx-upd
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 68b21fe063dcd55e6acaf59f480e58710e514466
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Dec 21 15:33:08 2023 +0100

    CAMEL-20274: camel-management - Add JMX operation to update route from XML
---
 .../catalog/main/camel-main-configuration-metadata.json |  1 +
 .../main/java/org/apache/camel/spi/ManagementAgent.java | 10 ++++++++++
 .../resources/org/apache/camel/core/xml/jmxAgent.json   |  3 ++-
 .../camel/core/xml/AbstractCamelContextFactoryBean.java |  4 ++++
 .../apache/camel/core/xml/CamelJMXAgentDefinition.java  | 17 +++++++++++++++++
 .../main/MainConfigurationPropertiesConfigurer.java     |  6 ++++++
 .../META-INF/camel-main-configuration-metadata.json     |  1 +
 core/camel-main/src/main/docs/main.adoc                 |  3 ++-
 .../camel/main/DefaultConfigurationConfigurer.java      |  2 ++
 .../camel/main/DefaultConfigurationProperties.java      | 15 +++++++++++++++
 .../camel/api/management/JmxSystemPropertyKeys.java     |  3 +++
 .../apache/camel/management/DefaultManagementAgent.java | 15 +++++++++++++++
 .../org/apache/camel/management/mbean/ManagedRoute.java |  6 ++++++
 .../management/DefaultManagementAgentMockTest.java      |  4 ++--
 .../management/ManagedRouteUpdateRouteFromXmlTest.java  | 11 +++++++++++
 dsl/camel-kamelet-main/src/main/docs/kamelet-main.adoc  |  1 +
 .../main/java/org/apache/camel/main/KameletMain.java    |  1 +
 17 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 3a1734b8152..23395908207 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -71,6 +71,7 @@
     { "name": "camel.main.jmxManagementMBeansLevel", "description": "Sets the mbeans registration level. The default value is Default.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.ManagementMBeansLevel", "defaultValue": "Default" },
     { "name": "camel.main.jmxManagementNamePattern", "description": "The naming pattern for creating the CamelContext JMX management name. The default pattern is #name#", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "#name#" },
     { "name": "camel.main.jmxManagementStatisticsLevel", "description": "Sets the JMX statistics level, the level can be set to Extended to gather additional information The default value is Default.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.ManagementStatisticsLevel", "defaultValue": "Default", "enum": [ "Extended", "Default", "RoutesOnly", "Off" ] },
+    { "name": "camel.main.jmxUpdateRouteEnabled", "description": "Whether to allow updating routes at runtime via JMX using the ManagedRouteMBean. This is disabled by default, but can be enabled for development and troubleshooting purposes, such as updating routes in an existing running Camel via JMX and other tools.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.lightweight", "description": "Configure the context to be lightweight. This will trigger some optimizations and memory reduction options. Lightweight context have some limitations. At this moment, dynamic endpoint destinations are not supported.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.loadHealthChecks", "description": "Whether to load custom health checks by scanning classpath.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.loadStatisticsEnabled", "description": "Sets whether context load statistics is enabled (something like the unix load average). The statistics requires to have camel-management on the classpath as JMX is required. The default value is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ManagementAgent.java b/core/camel-api/src/main/java/org/apache/camel/spi/ManagementAgent.java
index 199ddb88fde..dba8ccd9057 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ManagementAgent.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ManagementAgent.java
@@ -326,4 +326,14 @@ public interface ManagementAgent extends Service {
      */
     void setUseHostIPAddress(Boolean useHostIPAddress);
 
+    /**
+     * Gets whether updating routes via JMX is allowed (is default disabled).
+     */
+    Boolean getUpdateRouteEnabled();
+
+    /**
+     * Sets whether updating routes via JMX is allowed (is default disabled).
+     */
+    void setUpdateRouteEnabled(Boolean updateRouteEnabled);
+
 }
diff --git a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jmxAgent.json b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jmxAgent.json
index 7077f5b6774..d5af413f381 100644
--- a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jmxAgent.json
+++ b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jmxAgent.json
@@ -26,6 +26,7 @@
     "endpointRuntimeStatisticsEnabled": { "index": 11, "kind": "attribute", "displayName": "Endpoint Runtime Statistics Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "A flag that indicates whether endpoint runtime statistics is enabled" },
     "includeHostName": { "index": 12, "kind": "attribute", "displayName": "Include Host Name", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "A flag that indicates whether to include hostname in JMX MBean names." },
     "useHostIPAddress": { "index": 13, "kind": "attribute", "displayName": "Use Host IPAddress", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "A flag that indicates whether to use hostname or IP Address in the service url." },
-    "mask": { "index": 14, "kind": "attribute", "displayName": "Mask", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "A flag that indicates whether to remove detected sensitive information (such as passwords) from MBean names and attributes." }
+    "mask": { "index": 14, "kind": "attribute", "displayName": "Mask", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "A flag that indicates whether to remove detected sensitive information (such as passwords) from MBean names and attributes." },
+    "updateRouteEnabled": { "index": 15, "kind": "attribute", "displayName": "Update Route Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether updating routes via JMX is allowed (is default disabled)." }
   }
 }
diff --git a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
index 316ccf72302..020b03f8f3b 100644
--- a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
+++ b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
@@ -726,6 +726,10 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
             if (camelJMXAgent.getMask() != null) {
                 properties.put("mask", CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getMask()));
             }
+            if (camelJMXAgent.getUpdateRouteEnabled() != null) {
+                properties.put("updateRouteEnabled",
+                        CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getUpdateRouteEnabled()));
+            }
             if (camelJMXAgent.getLoadStatisticsEnabled() != null) {
                 properties.put("loadStatisticsEnabled",
                         CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getLoadStatisticsEnabled()));
diff --git a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelJMXAgentDefinition.java b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelJMXAgentDefinition.java
index 591c409e129..cab7726eecc 100644
--- a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelJMXAgentDefinition.java
+++ b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelJMXAgentDefinition.java
@@ -76,6 +76,9 @@ public class CamelJMXAgentDefinition extends IdentifiedType {
     @XmlAttribute
     @Metadata(defaultValue = "true", javaType = "java.lang.Boolean")
     private String mask;
+    @XmlAttribute
+    @Metadata(defaultValue = "false", javaType = "java.lang.Boolean")
+    private String updateRouteEnabled;
 
     public String getDisabled() {
         return disabled;
@@ -234,6 +237,17 @@ public class CamelJMXAgentDefinition extends IdentifiedType {
         this.useHostIPAddress = useHostIPAddress;
     }
 
+    public String getUpdateRouteEnabled() {
+        return updateRouteEnabled;
+    }
+
+    /**
+     * Sets whether updating routes via JMX is allowed (is default disabled).
+     */
+    public void setUpdateRouteEnabled(String updateRouteEnabled) {
+        this.updateRouteEnabled = updateRouteEnabled;
+    }
+
     @Override
     public String toString() {
         StringJoiner buffer = new StringJoiner(", ", "CamelJMXAgent[", "]");
@@ -276,6 +290,9 @@ public class CamelJMXAgentDefinition extends IdentifiedType {
         if (mask != null) {
             buffer.add("mask=" + mask);
         }
+        if (updateRouteEnabled != null) {
+            buffer.add("updateRouteEnabled=" + updateRouteEnabled);
+        }
         return buffer.toString();
     }
 
diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
index 6c7daa578bc..ca08ad52360 100644
--- a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
+++ b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
@@ -127,6 +127,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "JmxManagementNamePattern": target.setJmxManagementNamePattern(property(camelContext, java.lang.String.class, value)); return true;
         case "jmxmanagementstatisticslevel":
         case "JmxManagementStatisticsLevel": target.setJmxManagementStatisticsLevel(property(camelContext, org.apache.camel.ManagementStatisticsLevel.class, value)); return true;
+        case "jmxupdaterouteenabled":
+        case "JmxUpdateRouteEnabled": target.setJmxUpdateRouteEnabled(property(camelContext, boolean.class, value)); return true;
         case "lightweight":
         case "Lightweight": target.setLightweight(property(camelContext, boolean.class, value)); return true;
         case "loadhealthchecks":
@@ -366,6 +368,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "JmxManagementNamePattern": return java.lang.String.class;
         case "jmxmanagementstatisticslevel":
         case "JmxManagementStatisticsLevel": return org.apache.camel.ManagementStatisticsLevel.class;
+        case "jmxupdaterouteenabled":
+        case "JmxUpdateRouteEnabled": return boolean.class;
         case "lightweight":
         case "Lightweight": return boolean.class;
         case "loadhealthchecks":
@@ -606,6 +610,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "JmxManagementNamePattern": return target.getJmxManagementNamePattern();
         case "jmxmanagementstatisticslevel":
         case "JmxManagementStatisticsLevel": return target.getJmxManagementStatisticsLevel();
+        case "jmxupdaterouteenabled":
+        case "JmxUpdateRouteEnabled": return target.isJmxUpdateRouteEnabled();
         case "lightweight":
         case "Lightweight": return target.isLightweight();
         case "loadhealthchecks":
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 3a1734b8152..23395908207 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
@@ -71,6 +71,7 @@
     { "name": "camel.main.jmxManagementMBeansLevel", "description": "Sets the mbeans registration level. The default value is Default.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.ManagementMBeansLevel", "defaultValue": "Default" },
     { "name": "camel.main.jmxManagementNamePattern", "description": "The naming pattern for creating the CamelContext JMX management name. The default pattern is #name#", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "#name#" },
     { "name": "camel.main.jmxManagementStatisticsLevel", "description": "Sets the JMX statistics level, the level can be set to Extended to gather additional information The default value is Default.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.ManagementStatisticsLevel", "defaultValue": "Default", "enum": [ "Extended", "Default", "RoutesOnly", "Off" ] },
+    { "name": "camel.main.jmxUpdateRouteEnabled", "description": "Whether to allow updating routes at runtime via JMX using the ManagedRouteMBean. This is disabled by default, but can be enabled for development and troubleshooting purposes, such as updating routes in an existing running Camel via JMX and other tools.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.lightweight", "description": "Configure the context to be lightweight. This will trigger some optimizations and memory reduction options. Lightweight context have some limitations. At this moment, dynamic endpoint destinations are not supported.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.loadHealthChecks", "description": "Whether to load custom health checks by scanning classpath.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.loadStatisticsEnabled", "description": "Sets whether context load statistics is enabled (something like the unix load average). The statistics requires to have camel-management on the classpath as JMX is required. The default value is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc
index 87322318756..45bfa21a833 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -19,7 +19,7 @@ The following tables lists all the options:
 
 // main options: START
 === Camel Main configurations
-The camel.main supports 116 options, which are listed below.
+The camel.main supports 117 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -77,6 +77,7 @@ The camel.main supports 116 options, which are listed below.
 | *camel.main.jmxManagementMBeans{zwsp}Level* | Sets the mbeans registration level. The default value is Default. | Default | ManagementMBeansLevel
 | *camel.main.jmxManagementName{zwsp}Pattern* | The naming pattern for creating the CamelContext JMX management name. The default pattern is #name# | #name# | String
 | *camel.main.jmxManagement{zwsp}StatisticsLevel* | Sets the JMX statistics level, the level can be set to Extended to gather additional information The default value is Default. | Default | ManagementStatisticsLevel
+| *camel.main.jmxUpdateRoute{zwsp}Enabled* | Whether to allow updating routes at runtime via JMX using the ManagedRouteMBean. This is disabled by default, but can be enabled for development and troubleshooting purposes, such as updating routes in an existing running Camel via JMX and other tools. | false | boolean
 | *camel.main.lightweight* | Configure the context to be lightweight. This will trigger some optimizations and memory reduction options. Lightweight context have some limitations. At this moment, dynamic endpoint destinations are not supported. | false | boolean
 | *camel.main.loadHealthChecks* | Whether to load custom health checks by scanning classpath. | false | boolean
 | *camel.main.loadStatistics{zwsp}Enabled* | Sets whether context load statistics is enabled (something like the unix load average). The statistics requires to have camel-management on the classpath as JMX is required. The default value is false. | false | boolean
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
index 1ed607290fa..c403d714a0e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
@@ -291,6 +291,8 @@ public final class DefaultConfigurationConfigurer {
                     .setMBeansLevel(config.getJmxManagementMBeansLevel());
             camelContext.getManagementStrategy().getManagementAgent()
                     .setManagementNamePattern(config.getJmxManagementNamePattern());
+            camelContext.getManagementStrategy().getManagementAgent()
+                    .setUpdateRouteEnabled(config.isJmxUpdateRouteEnabled());
         }
         if (config.isCamelEventsTimestampEnabled()) {
             camelContext.getManagementStrategy().getEventFactory().setTimestampEnabled(true);
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 3cdff9ae560..2e3fc64a8f3 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
@@ -131,6 +131,7 @@ public abstract class DefaultConfigurationProperties<T> {
     private String exchangeFactory = "default";
     private int exchangeFactoryCapacity = 100;
     private boolean exchangeFactoryStatisticsEnabled;
+    private boolean jmxUpdateRouteEnabled;
     @Metadata(enums = "xml,yaml")
     private String dumpRoutes;
     private String dumpRoutesInclude = "routes";
@@ -1326,6 +1327,20 @@ public abstract class DefaultConfigurationProperties<T> {
         this.routesReloadRestartDuration = routesReloadRestartDuration;
     }
 
+    public boolean isJmxUpdateRouteEnabled() {
+        return jmxUpdateRouteEnabled;
+    }
+
+    /**
+     * Whether to allow updating routes at runtime via JMX using the ManagedRouteMBean.
+     *
+     * This is disabled by default, but can be enabled for development and troubleshooting purposes, such as updating
+     * routes in an existing running Camel via JMX and other tools.
+     */
+    public void setJmxUpdateRouteEnabled(boolean jmxUpdateRouteEnabled) {
+        this.jmxUpdateRouteEnabled = jmxUpdateRouteEnabled;
+    }
+
     public boolean isLightweight() {
         return lightweight;
     }
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/JmxSystemPropertyKeys.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/JmxSystemPropertyKeys.java
index 99d8b0dffb8..51eafd2897f 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/JmxSystemPropertyKeys.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/JmxSystemPropertyKeys.java
@@ -64,6 +64,9 @@ public final class JmxSystemPropertyKeys {
     // flag to enable host ip address instead of host name
     public static final String USE_HOST_IP_ADDRESS = "org.apache.camel.jmx.useHostIPAddress";
 
+    // flag to enable updating routes via XML
+    public static final String UPDATE_ROUTE_ENABLED = "org.apache.camel.jmx.updateRouteEnabled";
+
     private JmxSystemPropertyKeys() {
         // not instantiated
     }
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementAgent.java b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementAgent.java
index 94b78e1eb86..ae761567c8a 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementAgent.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementAgent.java
@@ -72,6 +72,7 @@ public class DefaultManagementAgent extends ServiceSupport implements Management
     private Boolean mask = true;
     private Boolean includeHostName = false;
     private Boolean useHostIPAddress = false;
+    private Boolean updateRouteEnabled = false;
     private String managementNamePattern = "#name#";
     private ManagementStatisticsLevel statisticsLevel = ManagementStatisticsLevel.Default;
     private ManagementMBeansLevel mBeansLevel = ManagementMBeansLevel.Default;
@@ -141,6 +142,10 @@ public class DefaultManagementAgent extends ServiceSupport implements Management
             useHostIPAddress = Boolean.getBoolean(JmxSystemPropertyKeys.USE_HOST_IP_ADDRESS);
             values.put(JmxSystemPropertyKeys.USE_HOST_IP_ADDRESS, useHostIPAddress);
         }
+        if (System.getProperty(JmxSystemPropertyKeys.UPDATE_ROUTE_ENABLED) != null) {
+            updateRouteEnabled = Boolean.getBoolean(JmxSystemPropertyKeys.UPDATE_ROUTE_ENABLED);
+            values.put(JmxSystemPropertyKeys.UPDATE_ROUTE_ENABLED, updateRouteEnabled);
+        }
 
         if (!values.isEmpty()) {
             LOG.info("ManagementAgent detected JVM system properties: {}", values);
@@ -297,6 +302,16 @@ public class DefaultManagementAgent extends ServiceSupport implements Management
         this.mBeansLevel = mBeansLevel;
     }
 
+    @Override
+    public Boolean getUpdateRouteEnabled() {
+        return updateRouteEnabled != null && updateRouteEnabled;
+    }
+
+    @Override
+    public void setUpdateRouteEnabled(Boolean updateRouteEnabled) {
+        this.updateRouteEnabled = updateRouteEnabled;
+    }
+
     @Override
     public CamelContext getCamelContext() {
         return camelContext;
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 0bd96f85748..27dcacf9339 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
@@ -678,6 +678,12 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
 
     @Override
     public void updateRouteFromXml(String xml) throws Exception {
+        // check whether this is allowed
+        Boolean enabled = context.getManagementStrategy().getManagementAgent().getUpdateRouteEnabled();
+        if (enabled == null || !enabled) {
+            throw new IllegalAccessException("Updating route is not enabled");
+        }
+
         // convert to model from xml
         ExtendedCamelContext ecc = context.getCamelContextExtension();
         InputStream is = context.getTypeConverter().convertTo(InputStream.class, xml);
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/DefaultManagementAgentMockTest.java b/core/camel-management/src/test/java/org/apache/camel/management/DefaultManagementAgentMockTest.java
index ec98268aa60..8e8c6ec344b 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/DefaultManagementAgentMockTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/DefaultManagementAgentMockTest.java
@@ -79,7 +79,7 @@ public class DefaultManagementAgentMockTest {
     }
 
     @Test
-    public void testShouldUseHostIPAddressWhenFlagisTrue() throws Exception {
+    public void testShouldUseHostIPAddressWhenFlagIsTrue() throws Exception {
         System.setProperty(JmxSystemPropertyKeys.USE_HOST_IP_ADDRESS, "true");
         try {
             CamelContext ctx = new DefaultCamelContext();
@@ -94,7 +94,7 @@ public class DefaultManagementAgentMockTest {
     }
 
     @Test
-    public void shouldUseHostNameWhenFlagisFalse() throws Exception {
+    public void shouldUseHostNameWhenFlagIsFalse() throws Exception {
         System.setProperty(JmxSystemPropertyKeys.USE_HOST_IP_ADDRESS, "false");
         try {
             CamelContext ctx = new DefaultCamelContext();
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteUpdateRouteFromXmlTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteUpdateRouteFromXmlTest.java
index 7ba41bffef7..378aa6ee7ad 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteUpdateRouteFromXmlTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteUpdateRouteFromXmlTest.java
@@ -21,6 +21,7 @@ import java.util.Set;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Test;
@@ -33,6 +34,16 @@ import static org.junit.jupiter.api.Assertions.fail;
 @DisabledOnOs(OS.AIX)
 public class ManagedRouteUpdateRouteFromXmlTest extends ManagementTestSupport {
 
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+
+        // enable updating route
+        context.getManagementStrategy().getManagementAgent().setUpdateRouteEnabled(true);
+
+        return context;
+    }
+
     @Test
     public void testUpdateRouteFromXml() throws Exception {
         MBeanServer mbeanServer = getMBeanServer();
diff --git a/dsl/camel-kamelet-main/src/main/docs/kamelet-main.adoc b/dsl/camel-kamelet-main/src/main/docs/kamelet-main.adoc
index d44520fc044..2caa3ec9d9f 100644
--- a/dsl/camel-kamelet-main/src/main/docs/kamelet-main.adoc
+++ b/dsl/camel-kamelet-main/src/main/docs/kamelet-main.adoc
@@ -23,6 +23,7 @@ The `KameletMain` is pre-configured with the following properties:
 camel.component.kamelet.location = classpath:/kamelets,github:apache:camel-kamelets/kamelets
 camel.component.rest.consumerComponentName = platform-http
 camel.component.rest.producerComponentName = vertx-http
+came.main.jmxUpdateRouteEnabled = true
 ----
 
 These settings can be overridden by configuration in `application.properties`.
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index ac0c743e291..f9480d9747e 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -718,6 +718,7 @@ public class KameletMain extends MainCommandLineSupport {
         addInitialProperty("camel.component.kamelet.location", location);
         addInitialProperty("camel.component.rest.consumerComponentName", "platform-http");
         addInitialProperty("camel.component.rest.producerComponentName", "vertx-http");
+        addInitialProperty("came.main.jmxUpdateRouteEnabled", "true");
     }
 
     protected String startupInfo() {