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 2020/12/23 14:08:19 UTC

[camel] branch master updated (d9c0388 -> b52d5f2)

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

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


    from d9c0388  CAMEL-15928: Fix not invoking fallback for resilience4j circuit breaker and not triggering circuit breaker for timeout exceptions (#4810)
     new be97224  CAMEL-15986: camel-core - DynamicAware need to support component alias. CAMEL-15984: camel-jms to support DynamicAware with toD
     new 6e7992b  CAMEL-15984: camel-activemq to support DynamicAware with toD
     new b52d5f2  CAMEL-15984: Added note in migration docs

The 3 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.


Summary of changes:
 .../org/apache/camel/send-dynamic/activemq         |   2 +
 .../activemq/ActiveMQSendDynamicAware.java         |  25 +++++
 .../activemq/ActiveMQToDSendDynamicTwoTest.java    |  56 +++++++++
 .../services/org/apache/camel/send-dynamic/jms     |   2 +
 .../camel/component/jms/JmsSendDynamicAware.java   | 125 +++++++++++++++++++++
 .../component/jms/JmsSendDynamicPostProcessor.java |  28 +++++
 .../camel/component/jms/JmsToDSendDynamicTest.java |  67 +++++++++++
 .../jms/JmsToDSendDynamicTwoDisabledTest.java      |  66 +++++++++++
 .../component/jms/JmsToDSendDynamicTwoTest.java    |  67 +++++++++++
 .../src/main/java/org/apache/camel/Component.java  |   7 ++
 .../camel/processor/SendDynamicProcessor.java      |  12 ++
 .../org/apache/camel/support/DefaultComponent.java |  28 +++--
 .../java/org/apache/camel/util/StringHelper.java   |  21 ++++
 .../org/apache/camel/util/StringHelperTest.java    |  11 +-
 .../ROOT/pages/camel-3x-upgrade-guide-3_8.adoc     |   4 +
 15 files changed, 510 insertions(+), 11 deletions(-)
 create mode 100644 components/camel-activemq/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/activemq
 create mode 100644 components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQSendDynamicAware.java
 create mode 100644 components/camel-activemq/src/test/java/org/apache/camel/component/activemq/ActiveMQToDSendDynamicTwoTest.java
 create mode 100644 components/camel-jms/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/jms
 create mode 100644 components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsSendDynamicAware.java
 create mode 100644 components/camel-jms/src/main/resources/org/apache/camel/component/jms/JmsSendDynamicPostProcessor.java
 create mode 100644 components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTest.java
 create mode 100644 components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoDisabledTest.java
 create mode 100644 components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoTest.java


[camel] 02/03: CAMEL-15984: camel-activemq to support DynamicAware with toD

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

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

commit 6e7992bfbcfddc48f59c5a0f891333052af940f1
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Dec 23 14:43:24 2020 +0100

    CAMEL-15984: camel-activemq to support DynamicAware with toD
---
 .../org/apache/camel/send-dynamic/activemq         |  2 +
 .../activemq/ActiveMQSendDynamicAware.java         | 25 ++++++++++
 .../activemq/ActiveMQToDSendDynamicTwoTest.java    | 56 ++++++++++++++++++++++
 3 files changed, 83 insertions(+)

diff --git a/components/camel-activemq/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/activemq b/components/camel-activemq/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/activemq
new file mode 100644
index 0000000..904f34c
--- /dev/null
+++ b/components/camel-activemq/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/activemq
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.activemq.ActiveMQSendDynamicAware
diff --git a/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQSendDynamicAware.java b/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQSendDynamicAware.java
new file mode 100644
index 0000000..cac9412
--- /dev/null
+++ b/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQSendDynamicAware.java
@@ -0,0 +1,25 @@
+/*
+ * 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.component.activemq;
+
+import org.apache.camel.component.jms.JmsSendDynamicAware;
+import org.apache.camel.spi.annotations.SendDynamic;
+
+@SendDynamic("activemq")
+public class ActiveMQSendDynamicAware extends JmsSendDynamicAware {
+
+}
diff --git a/components/camel-activemq/src/test/java/org/apache/camel/component/activemq/ActiveMQToDSendDynamicTwoTest.java b/components/camel-activemq/src/test/java/org/apache/camel/component/activemq/ActiveMQToDSendDynamicTwoTest.java
new file mode 100644
index 0000000..7cc5653
--- /dev/null
+++ b/components/camel-activemq/src/test/java/org/apache/camel/component/activemq/ActiveMQToDSendDynamicTwoTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.component.activemq;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.component.activemq.ActiveMQComponent.activeMQComponent;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ActiveMQToDSendDynamicTwoTest extends CamelTestSupport {
+
+    @Test
+    public void testToD() throws Exception {
+        template.sendBodyAndHeader("direct:start", "Hello bar", "where", "bar");
+        template.sendBodyAndHeader("direct:start", "Hello beer", "where", "beer");
+        template.sendBodyAndHeader("direct:start", "Hello gin", "where", "gin");
+
+        template.sendBodyAndHeader("direct:start2", "Hello beer", "where2", "beer");
+        template.sendBodyAndHeader("direct:start2", "Hello whiskey", "where2", "whiskey");
+
+        // there should be 2 activemq endpoint
+        long count = context.getEndpoints().stream().filter(e -> e.getEndpointUri().startsWith("activemq:")).count();
+        assertEquals(2, count, "There should only be 2 activemq endpoint");
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                context.addComponent("activemq", activeMQComponent("vm://localhost?broker.persistent=false"));
+
+                // route message dynamic using toD
+                from("direct:start").toD("activemq:queue:${header.where}");
+
+                from("direct:start2").toD("activemq:queue:${header.where2}");
+            }
+        };
+    }
+}


[camel] 03/03: CAMEL-15984: Added note in migration docs

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

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

commit b52d5f29ee639fb8227789d46d6b9b7c14150da0
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Dec 23 14:45:46 2020 +0100

    CAMEL-15984: Added note in migration docs
---
 docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc
index b5d6c69..3d7f27c 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc
@@ -6,6 +6,10 @@ from both 3.0 to 3.1 and 3.1 to 3.2.
 
 == Upgrading Camel 3.7 to 3.8
 
+=== camel-activemq and camel-jms
+
+The JMS and ActiveMQ component now supports optimized toD EIP pattern by using a single endpoint/producer for dynamic destination names.
+
 === Camel-AWS2-SNS
 
 The policy option now expects a file, since the policy are going to be complex. It can be from classpath:, http: or file: etc.


[camel] 01/03: CAMEL-15986: camel-core - DynamicAware need to support component alias. CAMEL-15984: camel-jms to support DynamicAware with toD

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

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

commit be97224338b58d49fdcd30dfa52365e5b9887e7b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Dec 23 14:38:09 2020 +0100

    CAMEL-15986: camel-core - DynamicAware need to support component alias. CAMEL-15984: camel-jms to support DynamicAware with toD
---
 .../services/org/apache/camel/send-dynamic/jms     |   2 +
 .../camel/component/jms/JmsSendDynamicAware.java   | 125 +++++++++++++++++++++
 .../component/jms/JmsSendDynamicPostProcessor.java |  28 +++++
 .../camel/component/jms/JmsToDSendDynamicTest.java |  67 +++++++++++
 .../jms/JmsToDSendDynamicTwoDisabledTest.java      |  66 +++++++++++
 .../component/jms/JmsToDSendDynamicTwoTest.java    |  67 +++++++++++
 .../src/main/java/org/apache/camel/Component.java  |   7 ++
 .../camel/processor/SendDynamicProcessor.java      |  12 ++
 .../org/apache/camel/support/DefaultComponent.java |  28 +++--
 .../java/org/apache/camel/util/StringHelper.java   |  21 ++++
 .../org/apache/camel/util/StringHelperTest.java    |  11 +-
 11 files changed, 423 insertions(+), 11 deletions(-)

diff --git a/components/camel-jms/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/jms b/components/camel-jms/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/jms
new file mode 100644
index 0000000..8dd2069
--- /dev/null
+++ b/components/camel-jms/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/jms
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.jms.JmsSendDynamicAware
diff --git a/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsSendDynamicAware.java b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsSendDynamicAware.java
new file mode 100644
index 0000000..11eab1c
--- /dev/null
+++ b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsSendDynamicAware.java
@@ -0,0 +1,125 @@
+/*
+ * 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.component.jms;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.spi.SendDynamicAware;
+import org.apache.camel.spi.annotations.SendDynamic;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.StringHelper;
+
+/**
+ * JMS based {@link org.apache.camel.spi.SendDynamicAware} which allows to optimise JMS components with the toD (dynamic
+ * to) DSL in Camel. This implementation optimises by allowing to provide dynamic parameters via
+ * {@link JmsConstants#JMS_DESTINATION_NAME} header instead of the endpoint uri. That allows to use a static endpoint
+ * and its producer to service dynamic requests.
+ */
+@SendDynamic("jms")
+public class JmsSendDynamicAware extends ServiceSupport implements SendDynamicAware {
+
+    private CamelContext camelContext;
+    private String scheme;
+
+    @Override
+    public String getScheme() {
+        return scheme;
+    }
+
+    @Override
+    public void setScheme(String scheme) {
+        this.scheme = scheme;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public boolean isOnlyDynamicQueryParameters() {
+        return true;
+    }
+
+    @Override
+    public boolean isLenientProperties() {
+        return false;
+    }
+
+    @Override
+    public DynamicAwareEntry prepare(Exchange exchange, String uri, String originalUri) throws Exception {
+        return new DynamicAwareEntry(uri, originalUri, null, null);
+    }
+
+    @Override
+    public String resolveStaticUri(Exchange exchange, DynamicAwareEntry entry) throws Exception {
+        String destination = parseDestinationName(entry.getUri());
+        if (destination != null) {
+            String originalDestination = parseDestinationName(entry.getOriginalUri());
+            if (!destination.equals(originalDestination)) {
+                // okay the destination was dynamic, so use the original as endpoint name
+                String answer = entry.getUri();
+                answer = StringHelper.replaceFirst(answer, destination, originalDestination);
+                return answer;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Processor createPreProcessor(Exchange exchange, DynamicAwareEntry entry) throws Exception {
+        if (exchange.getMessage().getHeader(JmsConstants.JMS_DESTINATION_NAME) != null) {
+            return null;
+        }
+
+        final String destinationName = parseDestinationName(entry.getUri());
+        return new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getMessage().setHeader(JmsConstants.JMS_DESTINATION_NAME, destinationName);
+            }
+        };
+    }
+
+    @Override
+    public Processor createPostProcessor(Exchange exchange, DynamicAwareEntry entry) throws Exception {
+        // no post processor is needed
+        return null;
+    }
+
+    private String parseDestinationName(String uri) {
+        // strip query
+        int pos = uri.indexOf('?');
+        if (pos != -1) {
+            uri = uri.substring(0, pos);
+        }
+        // destination name is after last colon
+        pos = uri.lastIndexOf(':');
+        if (pos != -1) {
+            return uri.substring(pos + 1);
+        } else {
+            return null;
+        }
+    }
+
+}
diff --git a/components/camel-jms/src/main/resources/org/apache/camel/component/jms/JmsSendDynamicPostProcessor.java b/components/camel-jms/src/main/resources/org/apache/camel/component/jms/JmsSendDynamicPostProcessor.java
new file mode 100644
index 0000000..2b15576
--- /dev/null
+++ b/components/camel-jms/src/main/resources/org/apache/camel/component/jms/JmsSendDynamicPostProcessor.java
@@ -0,0 +1,28 @@
+/*
+ * 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.component.jms;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+
+public class JmsSendDynamicPostProcessor implements Processor {
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        exchange.getMessage().removeHeader(JmsConstants.JMS_DESTINATION_NAME);
+    }
+}
diff --git a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTest.java b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTest.java
new file mode 100644
index 0000000..fb75eed
--- /dev/null
+++ b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.component.jms;
+
+import javax.jms.ConnectionFactory;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.component.jms.JmsComponent.jmsComponentAutoAcknowledge;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class JmsToDSendDynamicTest extends CamelTestSupport {
+
+    @Test
+    public void testToD() throws Exception {
+        template.sendBodyAndHeader("direct:start", "Hello bar", "where", "bar");
+        template.sendBodyAndHeader("direct:start", "Hello beer", "where", "beer");
+
+        // there should only be one activemq endpoint
+        long count = context.getEndpoints().stream().filter(e -> e.getEndpointUri().startsWith("activemq:")).count();
+        assertEquals(1, count, "There should only be 1 activemq endpoint");
+
+        // and the messages should be in the queues
+        String out = consumer.receiveBody("activemq:queue:bar", 2000, String.class);
+        assertEquals("Hello bar", out);
+        out = consumer.receiveBody("activemq:queue:beer", 2000, String.class);
+        assertEquals("Hello beer", out);
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext camelContext = super.createCamelContext();
+
+        ConnectionFactory connectionFactory = CamelJmsTestHelper.createPersistentConnectionFactory();
+        camelContext.addComponent("activemq", jmsComponentAutoAcknowledge(connectionFactory));
+
+        return camelContext;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // route message dynamic using toD
+                from("direct:start").toD("activemq:queue:${header.where}");
+            }
+        };
+    }
+}
diff --git a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoDisabledTest.java b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoDisabledTest.java
new file mode 100644
index 0000000..b125115
--- /dev/null
+++ b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoDisabledTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.jms;
+
+import javax.jms.ConnectionFactory;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.component.jms.JmsComponent.jmsComponentAutoAcknowledge;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class JmsToDSendDynamicTwoDisabledTest extends CamelTestSupport {
+
+    @Test
+    public void testToD() throws Exception {
+        template.sendBodyAndHeader("direct:start", "Hello bar", "where", "bar");
+        template.sendBodyAndHeader("direct:start", "Hello beer", "where", "beer");
+        template.sendBodyAndHeader("direct:start", "Hello gin", "where", "gin");
+
+        template.sendBodyAndHeader("direct:start2", "Hello beer", "where2", "beer");
+        template.sendBodyAndHeader("direct:start2", "Hello whiskey", "where2", "whiskey");
+
+        // there should be 4 activemq endpoint
+        long count = context.getEndpoints().stream().filter(e -> e.getEndpointUri().startsWith("activemq:")).count();
+        assertEquals(4, count, "There should be 4 activemq endpoint");
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext camelContext = super.createCamelContext();
+
+        ConnectionFactory connectionFactory = CamelJmsTestHelper.createPersistentConnectionFactory();
+        camelContext.addComponent("activemq", jmsComponentAutoAcknowledge(connectionFactory));
+
+        return camelContext;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // route message dynamic using toD but turn off send dynamic aware
+                from("direct:start").toD().allowOptimisedComponents(false).uri("activemq:queue:${header.where}");
+                from("direct:start2").toD().allowOptimisedComponents(false).uri("activemq:queue:${header.where2}");
+            }
+        };
+    }
+}
diff --git a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoTest.java b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoTest.java
new file mode 100644
index 0000000..83f92ce
--- /dev/null
+++ b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsToDSendDynamicTwoTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.component.jms;
+
+import javax.jms.ConnectionFactory;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.component.jms.JmsComponent.jmsComponentAutoAcknowledge;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class JmsToDSendDynamicTwoTest extends CamelTestSupport {
+
+    @Test
+    public void testToD() throws Exception {
+        template.sendBodyAndHeader("direct:start", "Hello bar", "where", "bar");
+        template.sendBodyAndHeader("direct:start", "Hello beer", "where", "beer");
+        template.sendBodyAndHeader("direct:start", "Hello gin", "where", "gin");
+
+        template.sendBodyAndHeader("direct:start2", "Hello beer", "where2", "beer");
+        template.sendBodyAndHeader("direct:start2", "Hello whiskey", "where2", "whiskey");
+
+        // there should be 2 activemq endpoint
+        long count = context.getEndpoints().stream().filter(e -> e.getEndpointUri().startsWith("activemq:")).count();
+        assertEquals(2, count, "There should only be 2 activemq endpoint");
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext camelContext = super.createCamelContext();
+
+        ConnectionFactory connectionFactory = CamelJmsTestHelper.createPersistentConnectionFactory();
+        camelContext.addComponent("activemq", jmsComponentAutoAcknowledge(connectionFactory));
+
+        return camelContext;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // route message dynamic using toD
+                from("direct:start").toD("activemq:queue:${header.where}");
+
+                from("direct:start2").toD("activemq:queue:${header.where2}");
+            }
+        };
+    }
+}
diff --git a/core/camel-api/src/main/java/org/apache/camel/Component.java b/core/camel-api/src/main/java/org/apache/camel/Component.java
index 298aa4e..3d0d548 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Component.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Component.java
@@ -115,4 +115,11 @@ public interface Component extends CamelContextAware, Service {
         return object;
     }
 
+    /**
+     * Gets the default name of the component.
+     */
+    default String getDefaultName() {
+        return null;
+    }
+
 }
diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
index da416aa..9f26dee 100644
--- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
@@ -19,6 +19,7 @@ package org.apache.camel.processor;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
+import org.apache.camel.Component;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePattern;
@@ -320,6 +321,17 @@ public class SendDynamicProcessor extends AsyncProcessorSupport implements IdAwa
                     // find out if the component can be optimised for send-dynamic
                     SendDynamicAwareResolver resolver = new SendDynamicAwareResolver();
                     dynamicAware = resolver.resolve(camelContext, scheme);
+                    if (dynamicAware == null) {
+                        // okay fallback and try with default component name
+                        Component comp = camelContext.getComponent(scheme, false, isAutoStartupComponents());
+                        if (comp != null) {
+                            String defaultScheme = comp.getDefaultName();
+                            if (!scheme.equals(defaultScheme)) {
+                                dynamicAware = resolver.resolve(camelContext, defaultScheme);
+                                dynamicAware.setScheme(scheme);
+                            }
+                        }
+                    }
                     if (dynamicAware != null) {
                         if (LOG.isDebugEnabled()) {
                             LOG.debug("Detected SendDynamicAware component: {} optimising toD: {}", scheme,
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
index cf3bdf1..e7e1982 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
@@ -62,6 +62,7 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
 
     private volatile PropertyConfigurer componentPropertyConfigurer;
     private volatile PropertyConfigurer endpointPropertyConfigurer;
+    private volatile String defaultName;
     private final List<Supplier<ComponentExtension>> extensions = new ArrayList<>();
     private CamelContext camelContext;
 
@@ -354,19 +355,28 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
     }
 
     @Override
+    public String getDefaultName() {
+        return defaultName;
+    }
+
+    @Override
     protected void doBuild() throws Exception {
-        org.apache.camel.spi.annotations.Component ann
-                = ObjectHelper.getAnnotation(this, org.apache.camel.spi.annotations.Component.class);
-        if (ann != null) {
-            String name = ann.value();
-            // just grab first scheme name if the component has scheme alias (eg http,https)
-            if (name.contains(",")) {
-                name = StringHelper.before(name, ",");
+        if (defaultName == null) {
+            org.apache.camel.spi.annotations.Component ann
+                    = ObjectHelper.getAnnotation(this, org.apache.camel.spi.annotations.Component.class);
+            if (ann != null) {
+                defaultName = ann.value();
+                // just grab first scheme name if the component has scheme alias (eg http,https)
+                if (defaultName.contains(",")) {
+                    defaultName = StringHelper.before(defaultName, ",");
+                }
             }
-            final String componentConfigurerName = name + "-component-configurer";
+        }
+        if (defaultName != null) {
+            final String componentConfigurerName = defaultName + "-component-configurer";
             componentPropertyConfigurer = getCamelContext().adapt(ExtendedCamelContext.class).getConfigurerResolver()
                     .resolvePropertyConfigurer(componentConfigurerName, getCamelContext());
-            final String endpointConfigurerName = name + "-endpoint-configurer";
+            final String endpointConfigurerName = defaultName + "-endpoint-configurer";
             endpointPropertyConfigurer = getCamelContext().adapt(ExtendedCamelContext.class).getConfigurerResolver()
                     .resolvePropertyConfigurer(endpointConfigurerName, getCamelContext());
         }
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
index 8199401..34607c5 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
@@ -310,6 +310,27 @@ public final class StringHelper {
     }
 
     /**
+     * Replaces the first from token in the given input string.
+     * <p/>
+     * This implementation is not recursive, not does it check for tokens in the replacement string.
+     *
+     * @param  input                    the input string
+     * @param  from                     the from string, must <b>not</b> be <tt>null</tt> or empty
+     * @param  to                       the replacement string, must <b>not</b> be empty
+     * @return                          the replaced string, or the input string if no replacement was needed
+     * @throws IllegalArgumentException if the input arguments is invalid
+     */
+    public static String replaceFirst(String input, String from, String to) {
+        int pos = input.indexOf(from);
+        if (pos != -1) {
+            int len = from.length();
+            return input.substring(0, pos) + to + input.substring(pos + len);
+        } else {
+            return input;
+        }
+    }
+
+    /**
      * Creates a json tuple with the given name/value pair.
      *
      * @param  name  the name
diff --git a/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java b/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java
index f2487c5..a75e476 100644
--- a/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java
+++ b/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java
@@ -18,8 +18,7 @@ package org.apache.camel.util;
 
 import org.junit.jupiter.api.Test;
 
-import static org.apache.camel.util.StringHelper.camelCaseToDash;
-import static org.apache.camel.util.StringHelper.splitWords;
+import static org.apache.camel.util.StringHelper.*;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 public class StringHelperTest {
@@ -67,4 +66,12 @@ public class StringHelperTest {
         assertEquals(1, arr.length);
         assertEquals("hello", arr[0]);
     }
+
+    @Test
+    public void testReplaceFirst() throws Exception {
+        assertEquals("jms:queue:bar", replaceFirst("jms:queue:bar", "foo", "bar"));
+        assertEquals("jms:queue:bar", replaceFirst("jms:queue:foo", "foo", "bar"));
+        assertEquals("jms:queue:bar?blah=123", replaceFirst("jms:queue:foo?blah=123", "foo", "bar"));
+        assertEquals("jms:queue:bar?blah=foo", replaceFirst("jms:queue:foo?blah=foo", "foo", "bar"));
+    }
 }