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 2018/03/08 10:45:51 UTC

[camel] 05/05: CAMEL-12330: Allow to configure more option on rabbitmq component level.

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 fd11cddb05e53719e3512fc3833901f7c918c406
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Mar 8 11:07:36 2018 +0100

    CAMEL-12330: Allow to configure more option on rabbitmq component level.
---
 .../src/main/docs/rabbitmq-component.adoc          | 54 ++++++++++++++++------
 .../component/rabbitmq/RabbitMQComponent.java      | 48 ++++++++++++++++++-
 .../camel/component/rabbitmq/RabbitMQEndpoint.java |  4 +-
 .../component/rabbitmq/RabbitMQComponentTest.java  |  4 +-
 .../RabbitMQLookupConnectionFactoryTest.java       | 44 ++++++++++++++++++
 .../java/sample/camel/SampleCamelApplication.java  | 13 ++++++
 .../src/main/resources/application.properties      |  3 +-
 .../springboot/RabbitMQComponentConfiguration.java | 33 +++++++++++++
 8 files changed, 183 insertions(+), 20 deletions(-)

diff --git a/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc b/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc
index 35f1e2f..30eca55 100644
--- a/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc
+++ b/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc
@@ -23,11 +23,21 @@ for this component:
 
 === URI format
 
+The old syntax is *deprecated*:
 [source,text]
 ----
 rabbitmq://hostname[:port]/exchangeName?[options]
 ----
 
+Instead the hostname and port is configured on the component level, or
+can be provided as uri query parameters instead.
+
+The new syntax is:
+[source,text]
+----
+rabbitmq:exchangeName?[options]
+----
+
 Where *hostname* is the hostname of the running rabbitmq instance or
 cluster. Port is optional and if not specified then defaults to the
 RabbitMQ client default (5672). The exchange name determines which
@@ -37,7 +47,7 @@ exchange name determines which exchange the queue will bind to.
 === Options
 
 // component options: START
-The RabbitMQ component supports 5 options which are listed below.
+The RabbitMQ component supports 7 options which are listed below.
 
 
 
@@ -48,6 +58,8 @@ The RabbitMQ component supports 5 options which are listed below.
 | *portNumber* (common) | Port number for the host with the running rabbitmq instance or cluster. | 5672 | int
 | *username* (security) | Username in case of authenticated access | guest | String
 | *password* (security) | Password for authenticated access | guest | String
+| *connectionFactory* (common) | To use a custom RabbitMQ connection factory. When this option is set, all connection options (connectionTimeout, requestedChannelMax...) set on URI are not used |  | ConnectionFactory
+| *autoDetectConnection Factory* (common) | Whether to auto-detect looking up RabbitMQ connection factory from the registry. When enabled and a single instance of the connection factory is found then it will be used. An explicit connection factory can be configured on the component or endpoint level which takes precedence. | true | boolean
 | *resolveProperty Placeholders* (advanced) | Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders. | true | boolean
 |===
 // component options: END
@@ -79,6 +91,7 @@ with the following path and query parameters:
 |===
 | Name | Description | Default | Type
 | *autoDelete* (common) | If it is true, the exchange will be deleted when it is no longer in use | true | boolean
+| *connectionFactory* (common) | To use a custom RabbitMQ connection factory. When this option is set, all connection options (connectionTimeout, requestedChannelMax...) set on URI are not used |  | ConnectionFactory
 | *connectionTimeout* (common) | Connection timeout | 60000 | int
 | *deadLetterExchange* (common) | The name of the dead letter exchange |  | String
 | *deadLetterExchangeType* (common) | The type of the dead letter exchange | direct | String
@@ -120,7 +133,6 @@ with the following path and query parameters:
 | *automaticRecoveryEnabled* (advanced) | Enables connection automatic recovery (uses connection implementation that performs automatic recovery when connection shutdown is not initiated by the application) |  | Boolean
 | *bindingArgs* (advanced) | *Deprecated* Key/value args for configuring the queue binding parameters when declare=true |  | Map
 | *clientProperties* (advanced) | Connection client properties (client info used in negotiating with the server) |  | Map
-| *connectionFactory* (advanced) | To use a custom RabbitMQ connection factory. When this option is set, all connection options (connectionTimeout, requestedChannelMax...) set on URI are not used |  | ConnectionFactory
 | *exchangeArgs* (advanced) | *Deprecated* Key/value args for configuring the exchange parameters when declare=true |  | Map
 | *exchangeArgsConfigurer* (advanced) | *Deprecated* Set the configurer for setting the exchange args in Channel.exchangeDeclare |  | ArgsConfigurer
 | *networkRecoveryInterval* (advanced) | Network recovery interval in milliseconds (interval used when recovering from network failure) | 5000 | Integer
@@ -164,7 +176,19 @@ And then refer to the connection factory in the endpoint uri as shown below:
 <camelContext>
   <route>
     <from uri="direct:rabbitMQEx2"/>
-    <to uri="rabbitmq://localhost:5672/ex2?connectionFactory=#rabbitConnectionFactory"/>
+    <to uri="rabbitmq:ex2?connectionFactory=#rabbitConnectionFactory"/>
+  </route>
+</camelContext>
+----
+
+From Camel 2.21 onwards the `ConnectionFactory` is auto-detected by default, so you can just do
+
+[source,xml]
+----
+<camelContext>
+  <route>
+    <from uri="direct:rabbitMQEx2"/>
+    <to uri="rabbitmq:ex2"/>
   </route>
 </camelContext>
 ----
@@ -255,7 +279,7 @@ routing key B,
 
 [source,java]
 ----
-from("rabbitmq://localhost/A?routingKey=B")
+from("rabbitmq:A?routingKey=B")
 ----
 
 To receive messages from a queue with a single thread with auto
@@ -263,21 +287,21 @@ acknowledge disabled.
 
 [source,java]
 ----
-from("rabbitmq://localhost/A?routingKey=B&threadPoolSize=1&autoAck=false")
+from("rabbitmq:A?routingKey=B&threadPoolSize=1&autoAck=false")
 ----
 
 To send messages to an exchange called C
 
 [source,java]
 ----
-to("rabbitmq://localhost/C")
+to("rabbitmq:C")
 ----
 
 Declaring a headers exchange and queue
 
 [source,java]
 ----
-from("rabbitmq://localhost/ex?exchangeType=headers&queue=q&bindingArgs=#bindArgs")
+from("rabbitmq:ex?exchangeType=headers&queue=q&bindingArgs=#bindArgs")
 ----
 
 and place corresponding `Map<String, Object>` with the id of "bindArgs" in the Registry.
@@ -299,8 +323,8 @@ in the example below with foo -> bar:
 
 [source,java]
 ----
-from("rabbitmq://localhost/foo")
-  .to("rabbitmq://localhost/bar")
+from("rabbitmq:foo")
+  .to("rabbitmq:bar")
 ----
 
 Then beware that Camel will route the message to itself, eg foo -> foo. So why is that?
@@ -315,17 +339,17 @@ To avoid this you need to either:
 
 [source,java]
 ----
-from("rabbitmq://localhost/foo")
+from("rabbitmq:foo")
   .removeHeader("rabbitmq.EXCHANGE_NAME")
-  .to("rabbitmq://localhost/bar")
+  .to("rabbitmq:bar")
 ----
 
 - Or turn on `bridgeEndpoint` mode on the producer:
 
 [source,java]
 ----
-from("rabbitmq://localhost/foo")
-  .to("rabbitmq://localhost/bar?bridgeEndpoint=true")
+from("rabbitmq:foo")
+  .to("rabbitmq:bar?bridgeEndpoint=true")
 ----
 
 From Camel 2.21 onwards this has been improved so you can easily route between exchanges.
@@ -335,8 +359,8 @@ For example to send to cheese exchange you can do
 
 [source,java]
 ----
-from("rabbitmq://localhost/foo")
+from("rabbitmq:foo")
   .setHeader("rabbitmq.EXCHANGE_OVERRIDE_NAME", constant("cheese"))
-  .to("rabbitmq://localhost/bar")
+  .to("rabbitmq:bar")
 ----
 
diff --git a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java
index 39515a3..d17fef4 100644
--- a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java
+++ b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java
@@ -18,7 +18,9 @@ package org.apache.camel.component.rabbitmq;
 
 import java.net.URI;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 import javax.net.ssl.TrustManager;
 
 import com.rabbitmq.client.ConnectionFactory;
@@ -46,6 +48,10 @@ public class RabbitMQComponent extends UriEndpointComponent {
     private String username = ConnectionFactory.DEFAULT_USER;
     @Metadata(label = "security", defaultValue = ConnectionFactory.DEFAULT_PASS, secret = true)
     private String password = ConnectionFactory.DEFAULT_PASS;
+    @Metadata(label = "common")
+    private ConnectionFactory connectionFactory;
+    @Metadata(label = "common", defaultValue = "true")
+    private boolean autoDetectConnectionFactory = true;
 
     public RabbitMQComponent() {
         super(RabbitMQEndpoint.class);
@@ -81,7 +87,22 @@ public class RabbitMQComponent extends UriEndpointComponent {
         }
 
         // ConnectionFactory reference
-        ConnectionFactory connectionFactory = resolveAndRemoveReferenceParameter(params, "connectionFactory", ConnectionFactory.class);
+        ConnectionFactory connectionFactory = resolveAndRemoveReferenceParameter(params, "connectionFactory", ConnectionFactory.class, getConnectionFactory());
+
+        // try to lookup if there is a single instance in the registry of the ConnectionFactory
+        if (connectionFactory == null && isAutoDetectConnectionFactory()) {
+            Map<String, ConnectionFactory> map = getCamelContext().getRegistry().findByTypeWithName(ConnectionFactory.class);
+            if (map != null && map.size() == 1) {
+                Map.Entry<String, ConnectionFactory> entry = map.entrySet().iterator().next();
+                connectionFactory = entry.getValue();
+                String name = entry.getKey();
+                if (name == null) {
+                    name = "anonymous";
+                }
+                LOG.info("Auto-detected single instance: {} of type ConnectionFactory in Registry to be used as ConnectionFactory when creating endpoint: {}", name, uri);
+            }
+        }
+
         @SuppressWarnings("unchecked")
         Map<String, Object> clientProperties = resolveAndRemoveReferenceParameter(params, "clientProperties", Map.class);
         TrustManager trustManager = resolveAndRemoveReferenceParameter(params, "trustManager", TrustManager.class);
@@ -163,4 +184,29 @@ public class RabbitMQComponent extends UriEndpointComponent {
         this.password = password;
     }
 
+    public ConnectionFactory getConnectionFactory() {
+        return connectionFactory;
+    }
+
+    /**
+     * To use a custom RabbitMQ connection factory. When this option is set, all
+     * connection options (connectionTimeout, requestedChannelMax...) set on URI
+     * are not used
+     */
+    public void setConnectionFactory(ConnectionFactory connectionFactory) {
+        this.connectionFactory = connectionFactory;
+    }
+
+    public boolean isAutoDetectConnectionFactory() {
+        return autoDetectConnectionFactory;
+    }
+
+    /**
+     * Whether to auto-detect looking up RabbitMQ connection factory from the registry.
+     * When enabled and a single instance of the connection factory is found then it will be used.
+     * An explicit connection factory can be configured on the component or endpoint level which takes precedence.
+     */
+    public void setAutoDetectConnectionFactory(boolean autoDetectConnectionFactory) {
+        this.autoDetectConnectionFactory = autoDetectConnectionFactory;
+    }
 }
diff --git a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java
index 1342a98..480fe73 100644
--- a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java
+++ b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java
@@ -66,6 +66,8 @@ public class RabbitMQEndpoint extends DefaultEndpoint implements AsyncEndpoint {
     private String password = ConnectionFactory.DEFAULT_PASS;
     @UriParam(defaultValue = ConnectionFactory.DEFAULT_VHOST)
     private String vhost = ConnectionFactory.DEFAULT_VHOST;
+    @UriParam(label = "common")
+    private ConnectionFactory connectionFactory;
     @UriParam(label = "consumer,advanced", defaultValue = "10")
     private int threadPoolSize = 10;
     @UriParam(label = "consumer", defaultValue = "true")
@@ -109,8 +111,6 @@ public class RabbitMQEndpoint extends DefaultEndpoint implements AsyncEndpoint {
     @UriParam(label = "advanced")
     private Map<String, Object> clientProperties;
     @UriParam(label = "advanced")
-    private ConnectionFactory connectionFactory;
-    @UriParam(label = "advanced")
     private Boolean automaticRecoveryEnabled;
     @UriParam(label = "advanced", defaultValue = "5000")
     private Integer networkRecoveryInterval = 5000;
diff --git a/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQComponentTest.java b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQComponentTest.java
index 5506aab..15de74b 100644
--- a/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQComponentTest.java
+++ b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQComponentTest.java
@@ -92,7 +92,9 @@ public class RabbitMQComponentTest {
         String uri = "rabbitmq:special.host:14/queuey";
         String remaining = "special.host:14/queuey";
 
-        return new RabbitMQComponent(context).createEndpoint(uri, remaining, params);
+        RabbitMQComponent comp = new RabbitMQComponent(context);
+        comp.setAutoDetectConnectionFactory(false);
+        return comp.createEndpoint(uri, remaining, params);
     }
 
     @Test
diff --git a/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQLookupConnectionFactoryTest.java b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQLookupConnectionFactoryTest.java
new file mode 100644
index 0000000..438688c
--- /dev/null
+++ b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQLookupConnectionFactoryTest.java
@@ -0,0 +1,44 @@
+/**
+ * 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.rabbitmq;
+
+import com.rabbitmq.client.ConnectionFactory;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class RabbitMQLookupConnectionFactoryTest extends CamelTestSupport {
+
+    private ConnectionFactory myConnectionFactory;
+
+    protected JndiRegistry createRegistry() throws Exception {
+        myConnectionFactory = new ConnectionFactory();
+        myConnectionFactory.setHost("myhost");
+
+        JndiRegistry registry = super.createRegistry();
+        registry.bind("myConnectionFactory", myConnectionFactory);
+        return registry;
+    }
+
+    @Test
+    public void testLookupConnectionFactory() throws Exception {
+        RabbitMQEndpoint endpoint = context.getEndpoint("rabbitmq:myexchange", RabbitMQEndpoint.class);
+        assertNotNull(endpoint);
+        assertSame(endpoint.getConnectionFactory(), myConnectionFactory);
+    }
+
+}
diff --git a/examples/camel-example-rabbitmq/src/main/java/sample/camel/SampleCamelApplication.java b/examples/camel-example-rabbitmq/src/main/java/sample/camel/SampleCamelApplication.java
index 5d9304a..5839aad 100644
--- a/examples/camel-example-rabbitmq/src/main/java/sample/camel/SampleCamelApplication.java
+++ b/examples/camel-example-rabbitmq/src/main/java/sample/camel/SampleCamelApplication.java
@@ -16,8 +16,10 @@
  */
 package sample.camel;
 
+import com.rabbitmq.client.ConnectionFactory;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
 
 //CHECKSTYLE:OFF
 /**
@@ -33,5 +35,16 @@ public class SampleCamelApplication {
         SpringApplication.run(SampleCamelApplication.class, args);
     }
 
+    /* You can also configure the RabbitMQ ConnectionFactory using Java code style
+    @Bean
+    public ConnectionFactory rabbitConnectionFactory() {
+        ConnectionFactory cf = new ConnectionFactory();
+        cf.setHost("localhost");
+        cf.setPort(5672);
+        cf.setUsername("cameltest");
+        cf.setPassword("cameltest");
+        return cf;
+    }
+    */
 }
 //CHECKSTYLE:ON
diff --git a/examples/camel-example-rabbitmq/src/main/resources/application.properties b/examples/camel-example-rabbitmq/src/main/resources/application.properties
index 279b2cd..e414fc0 100644
--- a/examples/camel-example-rabbitmq/src/main/resources/application.properties
+++ b/examples/camel-example-rabbitmq/src/main/resources/application.properties
@@ -33,7 +33,8 @@ management.security.enabled = false
 # turn on actuator health check
 endpoints.health.enabled = true
 
-# configure connection to the rabbit mq broker
+# configure connection to the rabbit mq broker using camel-rabbitmq style
+# note you can also configure from Java code, see SampleCamelApplication.java
 camel.component.rabbitmq.hostname=localhost
 camel.component.rabbitmq.port-number=5672
 camel.component.rabbitmq.username=guest
diff --git a/platforms/spring-boot/components-starter/camel-rabbitmq-starter/src/main/java/org/apache/camel/component/rabbitmq/springboot/RabbitMQComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-rabbitmq-starter/src/main/java/org/apache/camel/component/rabbitmq/springboot/RabbitMQComponentConfiguration.java
index 163f892..9bee754 100644
--- a/platforms/spring-boot/components-starter/camel-rabbitmq-starter/src/main/java/org/apache/camel/component/rabbitmq/springboot/RabbitMQComponentConfiguration.java
+++ b/platforms/spring-boot/components-starter/camel-rabbitmq-starter/src/main/java/org/apache/camel/component/rabbitmq/springboot/RabbitMQComponentConfiguration.java
@@ -17,8 +17,10 @@
 package org.apache.camel.component.rabbitmq.springboot;
 
 import javax.annotation.Generated;
+import com.rabbitmq.client.ConnectionFactory;
 import org.apache.camel.spring.boot.ComponentConfigurationPropertiesCommon;
 import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
 
 /**
  * The rabbitmq component allows you produce and consume messages from RabbitMQ
@@ -49,6 +51,20 @@ public class RabbitMQComponentConfiguration
      */
     private String password = "guest";
     /**
+     * To use a custom RabbitMQ connection factory. When this option is set, all
+     * connection options (connectionTimeout, requestedChannelMax...) set on URI
+     * are not used
+     */
+    @NestedConfigurationProperty
+    private ConnectionFactory connectionFactory;
+    /**
+     * Whether to auto-detect looking up RabbitMQ connection factory from the
+     * registry. When enabled and a single instance of the connection factory is
+     * found then it will be used. An explicit connection factory can be
+     * configured on the component or endpoint level which takes precedence.
+     */
+    private Boolean autoDetectConnectionFactory = true;
+    /**
      * Whether the component should resolve property placeholders on itself when
      * starting. Only properties which are of String type can use property
      * placeholders.
@@ -87,6 +103,23 @@ public class RabbitMQComponentConfiguration
         this.password = password;
     }
 
+    public ConnectionFactory getConnectionFactory() {
+        return connectionFactory;
+    }
+
+    public void setConnectionFactory(ConnectionFactory connectionFactory) {
+        this.connectionFactory = connectionFactory;
+    }
+
+    public Boolean getAutoDetectConnectionFactory() {
+        return autoDetectConnectionFactory;
+    }
+
+    public void setAutoDetectConnectionFactory(
+            Boolean autoDetectConnectionFactory) {
+        this.autoDetectConnectionFactory = autoDetectConnectionFactory;
+    }
+
     public Boolean getResolvePropertyPlaceholders() {
         return resolvePropertyPlaceholders;
     }

-- 
To stop receiving notification emails like this one, please contact
davsclaus@apache.org.