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

oscerd pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.18.x by this push:
     new a1132971f3d6 CAMEL-24576: dynamic-router - gate control message 
predicate (#26019)
a1132971f3d6 is described below

commit a1132971f3d64fd4d1dc748c3bfa87c49130ac9b
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Sep 2 09:23:24 2026 +0200

    CAMEL-24576: dynamic-router - gate control message predicate (#26019)
    
    Backport of #25992 onto camel-4.18.x, reduced to the control endpoint gate.
    
    This branch has no security marker attributes on @UriParam, no SecurityUtils
    insecure-options registry, and no RecipientList.setAllowedSchemes, so the
    insecure:dev marker and the allowedSchemes option are left out.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
    Claude-Session: https://claude.ai/code/session_013xhhhvd8YPrPXuXxL1ULdt
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../catalog/components/dynamic-router-control.json |   3 +-
 .../DynamicRouterControlEndpointConfigurer.java    |   6 +
 .../DynamicRouterControlEndpointUriFactory.java    |   3 +-
 .../control/dynamic-router-control.json            |   3 +-
 .../src/main/docs/dynamic-router-component.adoc    |  15 ++-
 .../docs/dynamic-router-control-component.adoc     |  31 +++++
 ...ynamicRouterControlChannelSendDynamicAware.java |   9 ++
 .../control/DynamicRouterControlConfiguration.java |  33 ++++++
 .../control/DynamicRouterControlConstants.java     |  16 +++
 .../control/DynamicRouterControlProducer.java      |  70 +++++++++---
 ...icRouterControlChannelSendDynamicAwareTest.java |  11 ++
 .../control/DynamicRouterControlProducerTest.java  | 126 +++++++++++++++++++++
 .../DynamicRouterBasicSynchronousIT.java           |   8 +-
 .../DynamicRouterSendDynamicAwareIT.java           |   3 +-
 ...DynamicRouterControlEndpointBuilderFactory.java |  42 +++++++
 15 files changed, 353 insertions(+), 26 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json
index 9f70a1e7523d..d8c4f25b440f 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json
@@ -46,6 +46,7 @@
     "predicateBean": { "index": 5, "kind": "parameter", "displayName": 
"Predicate Bean", "group": "control", "label": "control", "required": false, 
"type": "object", "javaType": "org.apache.camel.Predicate", "deprecated": 
false, "autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "A Predicate instance in 
the registry." },
     "priority": { "index": 6, "kind": "parameter", "displayName": "Priority", 
"group": "control", "label": "control", "required": false, "type": "integer", 
"javaType": "java.lang.Integer", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The subscription 
priority." },
     "subscribeChannel": { "index": 7, "kind": "parameter", "displayName": 
"Subscribe Channel", "group": "control", "label": "control", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The channel to 
subscribe to" },
-    "subscriptionId": { "index": 8, "kind": "parameter", "displayName": 
"Subscription Id", "group": "control", "label": "control", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The subscription ID; if 
unspecified, one will be assigned and returned." }
+    "subscriptionId": { "index": 8, "kind": "parameter", "displayName": 
"Subscription Id", "group": "control", "label": "control", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The subscription ID; if 
unspecified, one will be assigned and returned." },
+    "allowPredicateFromMessage": { "index": 9, "kind": "parameter", 
"displayName": "Allow Predicate From Message", "group": "security", "label": 
"control,security", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "Whether the subscripti 
[...]
   }
 }
diff --git 
a/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointConfigurer.java
 
b/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointConfigurer.java
index 65978aadf7f5..6eaaebe11bff 100644
--- 
a/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointConfigurer.java
+++ 
b/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointConfigurer.java
@@ -23,6 +23,8 @@ public class DynamicRouterControlEndpointConfigurer extends 
PropertyConfigurerSu
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         DynamicRouterControlEndpoint target = (DynamicRouterControlEndpoint) 
obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowpredicatefrommessage":
+        case "allowPredicateFromMessage": 
target.getConfiguration().setAllowPredicateFromMessage(property(camelContext, 
boolean.class, value)); return true;
         case "destinationuri":
         case "destinationUri": 
target.getConfiguration().setDestinationUri(property(camelContext, 
java.lang.String.class, value)); return true;
         case "expressionlanguage":
@@ -44,6 +46,8 @@ public class DynamicRouterControlEndpointConfigurer extends 
PropertyConfigurerSu
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowpredicatefrommessage":
+        case "allowPredicateFromMessage": return boolean.class;
         case "destinationuri":
         case "destinationUri": return java.lang.String.class;
         case "expressionlanguage":
@@ -66,6 +70,8 @@ public class DynamicRouterControlEndpointConfigurer extends 
PropertyConfigurerSu
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         DynamicRouterControlEndpoint target = (DynamicRouterControlEndpoint) 
obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowpredicatefrommessage":
+        case "allowPredicateFromMessage": return 
target.getConfiguration().isAllowPredicateFromMessage();
         case "destinationuri":
         case "destinationUri": return 
target.getConfiguration().getDestinationUri();
         case "expressionlanguage":
diff --git 
a/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointUriFactory.java
 
b/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointUriFactory.java
index 3b2f543db380..542a7017607e 100644
--- 
a/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointUriFactory.java
+++ 
b/components/camel-dynamic-router/src/generated/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpointUriFactory.java
@@ -23,7 +23,8 @@ public class DynamicRouterControlEndpointUriFactory extends 
org.apache.camel.sup
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Map<String, String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(9);
+        Set<String> props = new HashSet<>(10);
+        props.add("allowPredicateFromMessage");
         props.add("controlAction");
         props.add("destinationUri");
         props.add("expressionLanguage");
diff --git 
a/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json
 
b/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json
index 9f70a1e7523d..d8c4f25b440f 100644
--- 
a/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json
+++ 
b/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json
@@ -46,6 +46,7 @@
     "predicateBean": { "index": 5, "kind": "parameter", "displayName": 
"Predicate Bean", "group": "control", "label": "control", "required": false, 
"type": "object", "javaType": "org.apache.camel.Predicate", "deprecated": 
false, "autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "A Predicate instance in 
the registry." },
     "priority": { "index": 6, "kind": "parameter", "displayName": "Priority", 
"group": "control", "label": "control", "required": false, "type": "integer", 
"javaType": "java.lang.Integer", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The subscription 
priority." },
     "subscribeChannel": { "index": 7, "kind": "parameter", "displayName": 
"Subscribe Channel", "group": "control", "label": "control", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The channel to 
subscribe to" },
-    "subscriptionId": { "index": 8, "kind": "parameter", "displayName": 
"Subscription Id", "group": "control", "label": "control", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The subscription ID; if 
unspecified, one will be assigned and returned." }
+    "subscriptionId": { "index": 8, "kind": "parameter", "displayName": 
"Subscription Id", "group": "control", "label": "control", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "The subscription ID; if 
unspecified, one will be assigned and returned." },
+    "allowPredicateFromMessage": { "index": 9, "kind": "parameter", 
"displayName": "Allow Predicate From Message", "group": "security", "label": 
"control,security", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "configurationClass": 
"org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConfiguration",
 "configurationField": "configuration", "description": "Whether the subscripti 
[...]
   }
 }
diff --git 
a/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc 
b/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc
index 32935b5b00b8..3ebae76f0796 100644
--- 
a/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc
+++ 
b/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc
@@ -265,7 +265,18 @@ producerTemplate.sendBody("kafka://subscriptions", 
mapper.writeValueAsString(con
 ----
 
 In another module, additional routing will serve as a bridge to get the 
message from Kafka to the control channel of the
-Dynamic Router:
+Dynamic Router.  The subscriptions above carry their predicate in the control 
message, so the bridge has to opt in with
+`allowPredicateFromMessage=true`.
+
+[WARNING]
+====
+`allowPredicateFromMessage` lets whoever puts a message on the bridged 
transport choose both the expression language and
+the expression that the Dynamic Router compiles and evaluates, which means it 
decides what runs inside the Camel
+process.  Only enable it when the transport that feeds the control channel is 
trusted.  When it is not, have the
+participants subscribe with `predicateBean`, which selects a `Predicate` that 
the route author bound in the registry,
+and leave the flag at its default of `false`.  See
+xref:dynamic-router-control-component.adoc[the control component 
documentation] for the alternatives.
+====
 
 .Bridge from Kafka to the Dynamic Router control channel
 [source,java]
@@ -276,7 +287,7 @@ RouteBuilder subscriptionRouter() {
         public void configure() {
             from("kafka:subscriptions")
                 .unmarshal().json(DynamicRouterControlMessage.class)
-                .to("dynamic-router-control:subscribe");
+                
.to("dynamic-router-control:subscribe?allowPredicateFromMessage=true");
         }
     };
 }
diff --git 
a/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc
 
b/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc
index 154439314a0a..a2012ee09438 100644
--- 
a/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc
+++ 
b/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc
@@ -32,6 +32,37 @@ include::partial$component-endpoint-options.adoc[]
 include::partial$component-endpoint-headers.adoc[]
 // component options: END
 
+== Supplying the subscription predicate
+
+A subscription needs a predicate that decides which exchanges the participant 
receives. There are three ways to supply
+one, and they differ in who chooses it:
+
+* `predicateBean` -- the name of a `Predicate` bound in the registry. The 
route author decides which predicates exist,
+and the control message only selects one of them by name.
+* `predicate` and `expressionLanguage` as control endpoint URI parameters -- 
the route author writes the expression, and
+every subscription made through that endpoint uses it.
+* `predicate` and `expressionLanguage` carried in the control message, in its 
body or its headers -- the sender of the
+control message chooses both the expression language and the expression.
+
+The third form is disabled by default. The predicate is compiled and then 
evaluated against every exchange on the
+channel, so letting the control message choose both the language and the 
expression means the sender of that message
+decides what runs inside the Camel process. Set 
`allowPredicateFromMessage=true` on the control endpoint to enable it,
+and only do so when control messages can only come from a trusted source:
+
+[source,java]
+----
+from("kafka:subscriptions")
+    .unmarshal().json(DynamicRouterControlMessage.class)
+    .to("dynamic-router-control:subscribe?allowPredicateFromMessage=true");
+----
+
+When `allowPredicateFromMessage` is `false`, which is the default, a control 
message that supplies a `predicate` or an
+`expressionLanguage` is rejected with an `IllegalArgumentException`. Prefer 
`predicateBean`, or configure the predicate
+on the endpoint, when control messages arrive from outside the application.
+
+Subscription parameters that the control message does not carry fall back to 
the values configured on the control
+endpoint, so a participant can send only the parameters that identify it and 
let the endpoint supply the rest.
+
 == Subscribing
 
 Subscribing can be achieved by using query parameters in the control endpoint 
URI, or by sending a
diff --git 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAware.java
 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAware.java
index 13662241b271..3e5d0a79731d 100644
--- 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAware.java
+++ 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAware.java
@@ -28,6 +28,7 @@ import org.apache.camel.spi.annotations.SendDynamic;
 import org.apache.camel.support.component.SendDynamicAwareSupport;
 import org.apache.camel.util.URISupport;
 
+import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.ALLOW_PREDICATE_FROM_MESSAGE_PROPERTY;
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.COMPONENT_SCHEME_CONTROL;
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.CONTROL_ACTION_PROPERTY;
 
@@ -95,6 +96,14 @@ public class DynamicRouterControlChannelSendDynamicAware 
extends SendDynamicAwar
         String uri = entry.getUri();
         if (DynamicRouterControlConstants.SHOULD_OPTIMIZE.test(uri)) {
             optimizedUri = URISupport.stripQuery(uri);
+            // The subscription parameters are carried as headers, but 
"allowPredicateFromMessage" decides whether a
+            // control message may supply the predicate at all, so it has to 
stay on the endpoint, where only the
+            // route author can set it. Stripping it here would make the 
endpoint fall back to the default of false.
+            Object allowPredicateFromMessage = 
entry.getProperties().get(ALLOW_PREDICATE_FROM_MESSAGE_PROPERTY);
+            if (allowPredicateFromMessage != null) {
+                optimizedUri = optimizedUri + "?" + 
ALLOW_PREDICATE_FROM_MESSAGE_PROPERTY + "="
+                               + allowPredicateFromMessage;
+            }
         }
         return optimizedUri;
     }
diff --git 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConfiguration.java
 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConfiguration.java
index 27a02fbe1684..03bb28d97ef1 100644
--- 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConfiguration.java
+++ 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConfiguration.java
@@ -80,6 +80,19 @@ public class DynamicRouterControlConfiguration {
     @UriParam(label = "control", defaultValue = "simple", description = "The 
subscription predicate language.")
     private String expressionLanguage = "simple";
 
+    /**
+     * Whether the subscription predicate, and the language used to compile 
it, may be taken from the incoming control
+     * message.
+     */
+    @UriParam(label = "control,security", defaultValue = "false",
+              description = "Whether the subscription predicate, and the 
language used to compile it, may be taken"
+                            + " from the incoming control message. When 
disabled, the predicate and expressionLanguage"
+                            + " configured on this endpoint are used instead. 
Enabling this lets the sender of a"
+                            + " control message choose both the expression 
language and the expression that the"
+                            + " Dynamic Router compiles into a live predicate, 
so only enable it when control messages"
+                            + " come from a trusted source.")
+    private boolean allowPredicateFromMessage;
+
     /**
      * The control action (subscribe or unsubscribe).
      *
@@ -237,6 +250,26 @@ public class DynamicRouterControlConfiguration {
         this.expressionLanguage = expressionLanguage;
     }
 
+    /**
+     * Whether the subscription predicate, and the language used to compile 
it, may be taken from the incoming control
+     * message.
+     *
+     * @return true if the control message may supply the predicate
+     */
+    public boolean isAllowPredicateFromMessage() {
+        return allowPredicateFromMessage;
+    }
+
+    /**
+     * Whether the subscription predicate, and the language used to compile 
it, may be taken from the incoming control
+     * message.
+     *
+     * @param allowPredicateFromMessage true if the control message may supply 
the predicate
+     */
+    public void setAllowPredicateFromMessage(final boolean 
allowPredicateFromMessage) {
+        this.allowPredicateFromMessage = allowPredicateFromMessage;
+    }
+
     public DynamicRouterControlConfiguration() {
         // Default constructor is empty because we need an instance, and
         // then things can be populated through mutator methods.
diff --git 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConstants.java
 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConstants.java
index c5516973453d..196cb80f8174 100644
--- 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConstants.java
+++ 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlConstants.java
@@ -124,6 +124,15 @@ public final class DynamicRouterControlConstants {
      */
     public static final String ERROR_NO_PREDICATE_BEAN_FOUND = "Predicate bean 
could not be found";
 
+    /**
+     * Error when a control message supplies a predicate expression, or the 
language to compile it with, but the control
+     * endpoint does not allow those to be taken from a control message.
+     */
+    public static final String ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED
+            = "The subscription predicate expression, and the language used to 
compile it, cannot be taken from a "
+              + "control message. Configure 'predicate' and 
'expressionLanguage' on the dynamic-router-control "
+              + "endpoint, or set 'allowPredicateFromMessage=true' to let the 
control message supply them.";
+
     /**
      * The configuration property for the control channel action.
      */
@@ -164,6 +173,13 @@ public final class DynamicRouterControlConstants {
      */
     public static final String EXPRESSION_LANGUAGE_PROPERTY = 
"expressionLanguage";
 
+    /**
+     * The configuration property that controls whether the predicate may be 
taken from a control message. Unlike the
+     * other properties, this one is deliberately absent from {@link 
#URI_PARAMS_TO_HEADER_NAMES}: it must stay on the
+     * endpoint, where only the route author can set it, and must never be 
settable from a message.
+     */
+    public static final String ALLOW_PREDICATE_FROM_MESSAGE_PROPERTY = 
"allowPredicateFromMessage";
+
     /**
      * Header name for the control action.
      */
diff --git 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducer.java
 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducer.java
index 178cd0903390..658969e6af3d 100644
--- 
a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducer.java
+++ 
b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducer.java
@@ -42,6 +42,7 @@ import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterCont
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.CONTROL_SUBSCRIBE_CHANNEL;
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.CONTROL_SUBSCRIPTION_ID;
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.ERROR_NO_PREDICATE_BEAN_FOUND;
+import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED;
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.SIMPLE_LANGUAGE;
 
 /**
@@ -74,29 +75,57 @@ public class DynamicRouterControlProducer extends 
HeaderSelectorProducer {
         this.configuration = configuration;
     }
 
+    /**
+     * Returns the value to use for a predicate parameter that a control 
message may try to supply. Unless the endpoint
+     * explicitly allows the predicate to come from the message, a 
message-supplied value is rejected, and the value
+     * configured on the endpoint is used instead. Without this, the sender of 
a control message would choose both the
+     * expression language and the expression that the Dynamic Router compiles 
into a live predicate.
+     *
+     * @param  allowFromMessage whether the endpoint allows the predicate to 
come from the control message
+     * @param  messageValue     the value found in the control message, if any
+     * @param  configValue      the value configured on the endpoint
+     * @return                  the value to use
+     */
+    static String predicateValueToUse(
+            final boolean allowFromMessage, final String messageValue, final 
String configValue) {
+        if (allowFromMessage) {
+            return messageValue;
+        }
+        if (ObjectHelper.isNotEmpty(messageValue)) {
+            throw new 
IllegalArgumentException(ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED);
+        }
+        return configValue;
+    }
+
     /**
      * Create a filter from parameters in the message body.
      *
      * @param  dynamicRouterControlService the {@link 
DynamicRouterControlService}
+     * @param  configuration               the configuration for the Dynamic 
Router Control
      * @param  message                     the message, where the body 
contains a control message
      * @param  update                      whether to update an existing 
filter (true) or add a new one (false)
      * @return                             the ID of the added filter
      */
     static String subscribeFromMessage(
             final DynamicRouterControlService dynamicRouterControlService,
+            final DynamicRouterControlConfiguration configuration,
             final Message message, final boolean update) {
         DynamicRouterControlMessage messageBody = 
message.getBody(DynamicRouterControlMessage.class);
         String subscriptionId = messageBody.getSubscriptionId();
         String subscribeChannel = messageBody.getSubscribeChannel();
         String destinationUri = messageBody.getDestinationUri();
         String priority = String.valueOf(messageBody.getPriority());
-        String predicate = messageBody.getPredicate();
         String predicateBean = messageBody.getPredicateBean();
-        String expressionLanguage = messageBody.getExpressionLanguage();
         if (ObjectHelper.isNotEmpty(predicateBean)) {
             return 
dynamicRouterControlService.subscribeWithPredicateBean(subscribeChannel, 
subscriptionId,
                     destinationUri, Integer.parseInt(priority), predicateBean, 
update);
-        } else if (ObjectHelper.isNotEmpty(predicate) && 
ObjectHelper.isNotEmpty(expressionLanguage)) {
+        }
+        boolean allowFromMessage = configuration.isAllowPredicateFromMessage();
+        String predicate = predicateValueToUse(allowFromMessage, 
messageBody.getPredicate(),
+                configuration.getPredicate());
+        String expressionLanguage = predicateValueToUse(allowFromMessage, 
messageBody.getExpressionLanguage(),
+                configuration.getExpressionLanguage());
+        if (ObjectHelper.isNotEmpty(predicate) && 
ObjectHelper.isNotEmpty(expressionLanguage)) {
             return 
dynamicRouterControlService.subscribeWithPredicateExpression(subscribeChannel, 
subscriptionId,
                     destinationUri, Integer.parseInt(priority), predicate, 
expressionLanguage, update);
         } else {
@@ -105,29 +134,38 @@ public class DynamicRouterControlProducer extends 
HeaderSelectorProducer {
     }
 
     /**
-     * Create a filter from parameters in message headers.
+     * Create a filter from parameters in message headers, falling back to the 
values configured on the endpoint for any
+     * parameter that the message does not carry.
      *
      * @param  dynamicRouterControlService the {@link 
DynamicRouterControlService}
+     * @param  configuration               the configuration for the Dynamic 
Router Control
      * @param  message                     the message, where the headers 
contain subscription params
      * @param  update                      whether to update an existing 
filter (true) or add a new one (false)
      * @return                             the ID of the added filter
      */
     static String subscribeFromHeaders(
             final DynamicRouterControlService dynamicRouterControlService,
+            final DynamicRouterControlConfiguration configuration,
             final Message message, final boolean update) {
         Map<String, Object> headers = message.getHeaders();
-        String subscriptionId = (String) headers.get(CONTROL_SUBSCRIPTION_ID);
-        String subscribeChannel = (String) 
headers.get(CONTROL_SUBSCRIBE_CHANNEL);
-        String destinationUri = (String) headers.get(CONTROL_DESTINATION_URI);
-        String priority = String.valueOf(headers.get(CONTROL_PRIORITY));
-        String predicate = (String) headers.get(CONTROL_PREDICATE);
+        String subscriptionId = (String) 
headers.getOrDefault(CONTROL_SUBSCRIPTION_ID, 
configuration.getSubscriptionId());
+        String subscribeChannel
+                = (String) headers.getOrDefault(CONTROL_SUBSCRIBE_CHANNEL, 
configuration.getSubscribeChannel());
+        String destinationUri = (String) 
headers.getOrDefault(CONTROL_DESTINATION_URI, 
configuration.getDestinationUri());
+        String priority = 
String.valueOf(headers.getOrDefault(CONTROL_PRIORITY, 
configuration.getPriority()));
         String predicateBean = (String) headers.get(CONTROL_PREDICATE_BEAN);
-        String expressionLanguage = Optional.ofNullable((String) 
headers.get(CONTROL_EXPRESSION_LANGUAGE))
-                .orElse(SIMPLE_LANGUAGE);
         if (ObjectHelper.isNotEmpty(predicateBean)) {
             return 
dynamicRouterControlService.subscribeWithPredicateBean(subscribeChannel, 
subscriptionId,
                     destinationUri, Integer.parseInt(priority), predicateBean, 
update);
-        } else if (ObjectHelper.isNotEmpty(predicate) && 
ObjectHelper.isNotEmpty(expressionLanguage)) {
+        }
+        boolean allowFromMessage = configuration.isAllowPredicateFromMessage();
+        String predicate = predicateValueToUse(allowFromMessage, (String) 
headers.get(CONTROL_PREDICATE),
+                configuration.getPredicate());
+        String expressionLanguage = Optional
+                .ofNullable(predicateValueToUse(allowFromMessage, (String) 
headers.get(CONTROL_EXPRESSION_LANGUAGE),
+                        configuration.getExpressionLanguage()))
+                .orElse(SIMPLE_LANGUAGE);
+        if (ObjectHelper.isNotEmpty(predicate) && 
ObjectHelper.isNotEmpty(expressionLanguage)) {
             return 
dynamicRouterControlService.subscribeWithPredicateExpression(subscribeChannel, 
subscriptionId,
                     destinationUri, Integer.parseInt(priority), predicate, 
expressionLanguage, update);
         } else {
@@ -147,9 +185,9 @@ public class DynamicRouterControlProducer extends 
HeaderSelectorProducer {
     public void performSubscribe(final Message message, AsyncCallback 
callback) {
         String filterId;
         if (message.getBody() instanceof DynamicRouterControlMessage) {
-            filterId = subscribeFromMessage(dynamicRouterControlService, 
message, false);
+            filterId = subscribeFromMessage(dynamicRouterControlService, 
configuration, message, false);
         } else {
-            filterId = subscribeFromHeaders(dynamicRouterControlService, 
message, false);
+            filterId = subscribeFromHeaders(dynamicRouterControlService, 
configuration, message, false);
         }
         message.setBody(filterId);
         callback.done(false);
@@ -190,9 +228,9 @@ public class DynamicRouterControlProducer extends 
HeaderSelectorProducer {
     public void performUpdate(final Message message, AsyncCallback callback) {
         String filterId;
         if (message.getBody() instanceof DynamicRouterControlMessage) {
-            filterId = subscribeFromMessage(dynamicRouterControlService, 
message, true);
+            filterId = subscribeFromMessage(dynamicRouterControlService, 
configuration, message, true);
         } else {
-            filterId = subscribeFromHeaders(dynamicRouterControlService, 
message, true);
+            filterId = subscribeFromHeaders(dynamicRouterControlService, 
configuration, message, true);
         }
         message.setBody(filterId);
         callback.done(false);
diff --git 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAwareTest.java
 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAwareTest.java
index 634d942297b5..deb7e48b812d 100644
--- 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAwareTest.java
+++ 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlChannelSendDynamicAwareTest.java
@@ -68,6 +68,17 @@ class DynamicRouterControlChannelSendDynamicAwareTest {
         }
     }
 
+    @Test
+    void resolveStaticUriRetainsAllowPredicateFromMessage() throws Exception {
+        String originalUri = 
"dynamic-router-control:subscribe?subscriptionId=testSub1&allowPredicateFromMessage=true";
+        String uri = 
"dynamic-router-control://subscribe?subscriptionId=testSub1&allowPredicateFromMessage=true";
+        try (DynamicRouterControlChannelSendDynamicAware testSubject = new 
DynamicRouterControlChannelSendDynamicAware()) {
+            SendDynamicAware.DynamicAwareEntry entry = 
testSubject.prepare(exchange, uri, originalUri);
+            String result = testSubject.resolveStaticUri(exchange, entry);
+            
assertEquals("dynamic-router-control://subscribe?allowPredicateFromMessage=true",
 result);
+        }
+    }
+
     @Test
     void resolveStaticUriShouldNotOptimize() throws Exception {
         String originalUri = 
"dynamic-router-ctrl:subscribe?subscriptionId=testSub1";
diff --git 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducerTest.java
 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducerTest.java
index f86a48d55575..fad05c24c670 100644
--- 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducerTest.java
+++ 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlProducerTest.java
@@ -48,6 +48,7 @@ import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterCont
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.CONTROL_PRIORITY;
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.CONTROL_SUBSCRIBE_CHANNEL;
 import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.CONTROL_SUBSCRIPTION_ID;
+import static 
org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants.ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.when;
@@ -89,6 +90,7 @@ class DynamicRouterControlProducerTest {
 
     @Test
     void performSubscribeAction() {
+        when(configuration.isAllowPredicateFromMessage()).thenReturn(true);
         String subscribeChannel = "testChannel";
         Map<String, Object> headers = Map.of(
                 CONTROL_ACTION_HEADER, CONTROL_ACTION_SUBSCRIBE,
@@ -107,6 +109,7 @@ class DynamicRouterControlProducerTest {
 
     @Test
     void performSubscribeActionWithEmptyExpressionLanguage() {
+        when(configuration.isAllowPredicateFromMessage()).thenReturn(true);
         String subscribeChannel = "testChannel";
         Map<String, Object> headers = Map.of(
                 CONTROL_ACTION_HEADER, CONTROL_ACTION_SUBSCRIBE,
@@ -155,6 +158,7 @@ class DynamicRouterControlProducerTest {
 
     @Test
     void performUpdateAction() {
+        when(configuration.isAllowPredicateFromMessage()).thenReturn(true);
         // First, perform initial subscription
         String subscribeChannel = "testChannel";
         Map<String, Object> headers = Map.of(
@@ -229,6 +233,7 @@ class DynamicRouterControlProducerTest {
 
     @Test
     void performSubscribeActionWithMessageInBody() {
+        when(configuration.isAllowPredicateFromMessage()).thenReturn(true);
         String subscribeChannel = "testChannel";
         DynamicRouterControlMessage subMsg = 
DynamicRouterControlMessage.Builder.newBuilder()
                 .subscribeChannel(subscribeChannel)
@@ -249,6 +254,7 @@ class DynamicRouterControlProducerTest {
 
     @Test
     void performSubscribeActionWithMessageInBodyWithEmptyExpressionLanguage() {
+        when(configuration.isAllowPredicateFromMessage()).thenReturn(true);
         String subscribeChannel = "testChannel";
         DynamicRouterControlMessage subMsg = 
DynamicRouterControlMessage.Builder.newBuilder()
                 .subscribeChannel(subscribeChannel)
@@ -266,6 +272,7 @@ class DynamicRouterControlProducerTest {
 
     @Test
     void performSubscribeActionWithMessageInBodyWithEmptyExpression() {
+        when(configuration.isAllowPredicateFromMessage()).thenReturn(true);
         String subscribeChannel = "testChannel";
         DynamicRouterControlMessage subMsg = 
DynamicRouterControlMessage.Builder.newBuilder()
                 .subscribeChannel(subscribeChannel)
@@ -302,6 +309,7 @@ class DynamicRouterControlProducerTest {
 
     @Test
     void performUpdateActionWithMessageInBody() {
+        when(configuration.isAllowPredicateFromMessage()).thenReturn(true);
         String subscribeChannel = "testChannel";
         DynamicRouterControlMessage subMsg = 
DynamicRouterControlMessage.Builder.newBuilder()
                 .subscribeChannel(subscribeChannel)
@@ -320,6 +328,124 @@ class DynamicRouterControlProducerTest {
                         subscribeChannel, "testId", "mock://test", 10, "true", 
"simple", true);
     }
 
+    @Test
+    void performSubscribeActionRejectsPredicateFromHeadersByDefault() {
+        Map<String, Object> headers = Map.of(
+                CONTROL_ACTION_HEADER, CONTROL_ACTION_SUBSCRIBE,
+                CONTROL_SUBSCRIBE_CHANNEL, "testChannel",
+                CONTROL_SUBSCRIPTION_ID, "testId",
+                CONTROL_DESTINATION_URI, "mock://test",
+                CONTROL_PREDICATE, "true",
+                CONTROL_EXPRESSION_LANGUAGE, "simple",
+                CONTROL_PRIORITY, 10);
+        when(message.getHeaders()).thenReturn(headers);
+        Exception ex = assertThrows(IllegalArgumentException.class, () -> 
producer.performSubscribe(message, callback));
+        assertEquals(ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED, 
ex.getMessage());
+        Mockito.verifyNoInteractions(controlService);
+    }
+
+    @Test
+    void performSubscribeActionRejectsExpressionLanguageFromHeadersByDefault() 
{
+        Map<String, Object> headers = Map.of(
+                CONTROL_ACTION_HEADER, CONTROL_ACTION_SUBSCRIBE,
+                CONTROL_SUBSCRIBE_CHANNEL, "testChannel",
+                CONTROL_SUBSCRIPTION_ID, "testId",
+                CONTROL_DESTINATION_URI, "mock://test",
+                CONTROL_EXPRESSION_LANGUAGE, "simple",
+                CONTROL_PRIORITY, 10);
+        when(message.getHeaders()).thenReturn(headers);
+        Exception ex = assertThrows(IllegalArgumentException.class, () -> 
producer.performSubscribe(message, callback));
+        assertEquals(ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED, 
ex.getMessage());
+        Mockito.verifyNoInteractions(controlService);
+    }
+
+    @Test
+    void performSubscribeActionRejectsPredicateFromMessageBodyByDefault() {
+        DynamicRouterControlMessage subMsg = 
DynamicRouterControlMessage.Builder.newBuilder()
+                .subscribeChannel("testChannel")
+                .subscriptionId("testId")
+                .destinationUri("mock://test")
+                .priority(10)
+                .predicate("true")
+                .expressionLanguage("simple")
+                .build();
+        when(message.getBody()).thenReturn(subMsg);
+        
when(message.getBody(DynamicRouterControlMessage.class)).thenReturn(subMsg);
+        Exception ex = assertThrows(IllegalArgumentException.class, () -> 
producer.performSubscribe(message, callback));
+        assertEquals(ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED, 
ex.getMessage());
+        Mockito.verifyNoInteractions(controlService);
+    }
+
+    @Test
+    void performUpdateActionRejectsPredicateFromMessageBodyByDefault() {
+        DynamicRouterControlMessage subMsg = 
DynamicRouterControlMessage.Builder.newBuilder()
+                .subscribeChannel("testChannel")
+                .subscriptionId("testId")
+                .destinationUri("mock://test")
+                .priority(10)
+                .predicate("true")
+                .expressionLanguage("simple")
+                .build();
+        when(message.getBody()).thenReturn(subMsg);
+        
when(message.getBody(DynamicRouterControlMessage.class)).thenReturn(subMsg);
+        Exception ex = assertThrows(IllegalArgumentException.class, () -> 
producer.performUpdate(message, callback));
+        assertEquals(ERROR_PREDICATE_FROM_MESSAGE_NOT_ALLOWED, 
ex.getMessage());
+        Mockito.verifyNoInteractions(controlService);
+    }
+
+    @Test
+    void performSubscribeActionUsesEndpointPredicateWhenMessageSuppliesNone() {
+        String subscribeChannel = "testChannel";
+        Map<String, Object> headers = Map.of(
+                CONTROL_ACTION_HEADER, CONTROL_ACTION_SUBSCRIBE,
+                CONTROL_SUBSCRIBE_CHANNEL, subscribeChannel,
+                CONTROL_SUBSCRIPTION_ID, "testId",
+                CONTROL_DESTINATION_URI, "mock://test",
+                CONTROL_PRIORITY, 10);
+        when(message.getHeaders()).thenReturn(headers);
+        when(configuration.getPredicate()).thenReturn("true");
+        when(configuration.getExpressionLanguage()).thenReturn("simple");
+        Mockito.doNothing().when(callback).done(false);
+        producer.performSubscribe(message, callback);
+        Mockito.verify(controlService, 
Mockito.times(1)).subscribeWithPredicateExpression(
+                subscribeChannel, "testId", "mock://test", 10, "true", 
"simple", false);
+    }
+
+    @Test
+    void 
performSubscribeActionFallsBackToEndpointParametersWhenHeadersAreAbsent() {
+        Map<String, Object> headers = Map.of(CONTROL_ACTION_HEADER, 
CONTROL_ACTION_SUBSCRIBE);
+        when(message.getHeaders()).thenReturn(headers);
+        when(configuration.getSubscribeChannel()).thenReturn("testChannel");
+        when(configuration.getSubscriptionId()).thenReturn("testId");
+        when(configuration.getDestinationUri()).thenReturn("mock://test");
+        when(configuration.getPriority()).thenReturn(10);
+        when(configuration.getPredicate()).thenReturn("true");
+        when(configuration.getExpressionLanguage()).thenReturn("simple");
+        Mockito.doNothing().when(callback).done(false);
+        producer.performSubscribe(message, callback);
+        Mockito.verify(controlService, 
Mockito.times(1)).subscribeWithPredicateExpression(
+                "testChannel", "testId", "mock://test", 10, "true", "simple", 
false);
+    }
+
+    @Test
+    void performSubscribeActionWithPredicateBeanIsUnaffectedByTheGate() {
+        String subscribeChannel = "testChannel";
+        Map<String, Object> headers = Map.of(
+                CONTROL_ACTION_HEADER, CONTROL_ACTION_SUBSCRIBE,
+                CONTROL_SUBSCRIBE_CHANNEL, subscribeChannel,
+                CONTROL_SUBSCRIPTION_ID, "testId",
+                CONTROL_DESTINATION_URI, "mock://test",
+                CONTROL_PREDICATE, "true",
+                CONTROL_EXPRESSION_LANGUAGE, "simple",
+                CONTROL_PRIORITY, 10,
+                CONTROL_PREDICATE_BEAN, "testPredicate");
+        when(message.getHeaders()).thenReturn(headers);
+        Mockito.doNothing().when(callback).done(false);
+        producer.performSubscribe(message, callback);
+        Mockito.verify(controlService, 
Mockito.times(1)).subscribeWithPredicateBean(
+                subscribeChannel, "testId", "mock://test", 10, 
"testPredicate", false);
+    }
+
     @Test
     void testPerformListAction() {
         String subscribeChannel = "testChannel";
diff --git 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterBasicSynchronousIT.java
 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterBasicSynchronousIT.java
index da957ccdc46c..8b21c21b624d 100644
--- 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterBasicSynchronousIT.java
+++ 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterBasicSynchronousIT.java
@@ -176,7 +176,7 @@ public class DynamicRouterBasicSynchronousIT {
                 .expressionLanguage("spel")
                 .build();
 
-        template.sendBody("dynamic-router-control:subscribe", controlMessage);
+        
template.sendBody("dynamic-router-control:subscribe?allowPredicateFromMessage=true",
 controlMessage);
 
         // Trigger events to subscribers
         template.sendBodyAndHeader("direct:start", "testMessage", "test", 
"testValue");
@@ -239,7 +239,7 @@ public class DynamicRouterBasicSynchronousIT {
                 .predicate("#{headers.test == 'testValue1'}")
                 .expressionLanguage("spel")
                 .build();
-        template.sendBody("dynamic-router-control:subscribe", controlMessage1);
+        
template.sendBody("dynamic-router-control:subscribe?allowPredicateFromMessage=true",
 controlMessage1);
 
         DynamicRouterControlMessage controlMessage2 = 
DynamicRouterControlMessage.Builder.newBuilder()
                 .subscribeChannel("test")
@@ -249,7 +249,7 @@ public class DynamicRouterBasicSynchronousIT {
                 .predicate("#{headers.test == 'testValue2'}")
                 .expressionLanguage("spel")
                 .build();
-        template.sendBody("dynamic-router-control:subscribe", controlMessage2);
+        
template.sendBody("dynamic-router-control:subscribe?allowPredicateFromMessage=true",
 controlMessage2);
 
         DynamicRouterControlMessage controlMessage3 = 
DynamicRouterControlMessage.Builder.newBuilder()
                 .subscribeChannel("test")
@@ -259,7 +259,7 @@ public class DynamicRouterBasicSynchronousIT {
                 .predicate("#{headers.test == 'testValue3'}")
                 .expressionLanguage("spel")
                 .build();
-        template.sendBody("dynamic-router-control:subscribe", controlMessage3);
+        
template.sendBody("dynamic-router-control:subscribe?allowPredicateFromMessage=true",
 controlMessage3);
 
         String filtersJson = template.requestBodyAndHeader("direct:list", "", 
"subscribeChannel", "test", String.class);
         Assertions.assertEquals(
diff --git 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterSendDynamicAwareIT.java
 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterSendDynamicAwareIT.java
index dfcc58352080..aae5c2e1d694 100644
--- 
a/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterSendDynamicAwareIT.java
+++ 
b/components/camel-dynamic-router/src/test/java/org/apache/camel/component/dynamicrouter/integration/DynamicRouterSendDynamicAwareIT.java
@@ -62,7 +62,8 @@ public class DynamicRouterSendDynamicAwareIT {
                              "&subscriptionId=${header.subscriptionId}" +
                              "&destinationUri=${header.destinationUri}" +
                              "&priority=${header.priority}" +
-                             "&predicate=${header.predicate}");
+                             "&predicate=${header.predicate}" +
+                             "&allowPredicateFromMessage=true");
             }
         });
     }
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DynamicRouterControlEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DynamicRouterControlEndpointBuilderFactory.java
index 9b9d0c56d7c3..e6bae5bd2a7b 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DynamicRouterControlEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DynamicRouterControlEndpointBuilderFactory.java
@@ -176,6 +176,48 @@ public interface 
DynamicRouterControlEndpointBuilderFactory {
             doSetProperty("subscriptionId", subscriptionId);
             return this;
         }
+        /**
+         * Whether the subscription predicate, and the language used to compile
+         * it, may be taken from the incoming control message. When disabled,
+         * the predicate and expressionLanguage configured on this endpoint are
+         * used instead. Enabling this lets the sender of a control message
+         * choose both the expression language and the expression that the
+         * Dynamic Router compiles into a live predicate, so only enable it 
when
+         * control messages come from a trusted source.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowPredicateFromMessage the value to set
+         * @return the dsl builder
+         */
+        default DynamicRouterControlEndpointBuilder 
allowPredicateFromMessage(boolean allowPredicateFromMessage) {
+            doSetProperty("allowPredicateFromMessage", 
allowPredicateFromMessage);
+            return this;
+        }
+        /**
+         * Whether the subscription predicate, and the language used to compile
+         * it, may be taken from the incoming control message. When disabled,
+         * the predicate and expressionLanguage configured on this endpoint are
+         * used instead. Enabling this lets the sender of a control message
+         * choose both the expression language and the expression that the
+         * Dynamic Router compiles into a live predicate, so only enable it 
when
+         * control messages come from a trusted source.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowPredicateFromMessage the value to set
+         * @return the dsl builder
+         */
+        default DynamicRouterControlEndpointBuilder 
allowPredicateFromMessage(String allowPredicateFromMessage) {
+            doSetProperty("allowPredicateFromMessage", 
allowPredicateFromMessage);
+            return this;
+        }
     }
 
     /**

Reply via email to