| = Spring RabbitMQ Component |
| :doctitle: Spring RabbitMQ |
| :shortname: spring-rabbitmq |
| :artifactid: camel-spring-rabbitmq |
| :description: Send and receive messages from RabbitMQ using Spring RabbitMQ client. |
| :since: 3.8 |
| :supportlevel: Stable |
| :tabs-sync-option: |
| :component-header: Both producer and consumer are supported |
| //Manually maintained attributes |
| :group: Spring |
| :camel-spring-boot-name: spring-rabbitmq |
| |
| *Since Camel {since}* |
| |
| *{component-header}* |
| |
| The Spring RabbitMQ component allows you to produce and consume messages from |
| http://www.rabbitmq.com/[RabbitMQ] instances. Using the Spring RabbitMQ |
| client. |
| |
| Maven users will need to add the following dependency to their `pom.xml` |
| for this component: |
| |
| [source,xml] |
| ---- |
| <dependency> |
| <groupId>org.apache.camel</groupId> |
| <artifactId>camel-spring-rabbitmq</artifactId> |
| <version>x.x.x</version> |
| <!-- use the same version as your Camel core version --> |
| </dependency> |
| ---- |
| |
| == URI format |
| |
| ---- |
| spring-rabbitmq:exchangeName?[options] |
| ---- |
| |
| The exchange name determines the exchange to which the produced |
| messages will be sent to. In the case of consumers, the exchange name |
| determines the exchange the queue will be bound to. |
| |
| // component-configure options: START |
| |
| // component-configure options: END |
| |
| // component options: START |
| include::partial$component-configure-options.adoc[] |
| include::partial$component-endpoint-options.adoc[] |
| // component options: END |
| |
| // endpoint options: START |
| |
| // endpoint options: END |
| // component headers: START |
| include::partial$component-endpoint-headers.adoc[] |
| // component headers: END |
| |
| == Using a connection factory |
| |
| To connect to RabbitMQ you need to setup a `ConnectionFactory` (same as with JMS) with the login details such as: |
| |
| TIP: It is recommended to use `CachingConnectionFactory` from spring-rabbit as it comes with connection pooling out of the box. |
| |
| [source,xml] |
| ---- |
| <bean id="rabbitConnectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"> |
| <property name="uri" value="amqp://lolcalhost:5672"/> |
| </bean> |
| ---- |
| |
| The `ConnectionFactory` is auto-detected by default, so you can just do |
| |
| [source,xml] |
| ---- |
| <camelContext> |
| <route> |
| <from uri="direct:cheese"/> |
| <to uri="spring-rabbitmq:foo?routingKey=cheese"/> |
| </route> |
| </camelContext> |
| ---- |
| |
| == Default Exchange Name |
| |
| To use default exchange name (which would be an empty exchange name in RabbitMQ) then you should use `default` as name |
| in the endpoint uri, such as: |
| |
| [source,java] |
| ---- |
| to("spring-rabbitmq:default?routingKey=foo") |
| ---- |
| |
| == Auto declare exchanges, queues and bindings |
| |
| Before you can send or receive messages from RabbitMQ, then exchanges, queues and bindings must be setup first. |
| |
| In development mode it may be desirable to let Camel automatic do this. |
| You can enable this by setting `autoDeclare=true` on the `SpringRabbitMQComponent`. |
| |
| Then Spring RabbitMQ will automatic necessary declare the elements and setup the binding between the exchange, queue and routing keys. |
| |
| The elements can be configured using the multi-valued `args` option. |
| |
| For example to specify the queue as durable and exclusive, you can configure the endpoint uri with `arg.queue.durable=true&arg.queue.exclusive=true`. |
| |
| *Exchanges* |
| |
| [width="100%",cols="10%,10%,70%,10%",options="header",] |
| |===================================================================== |
| |Option |Type |Description|Default |
| | autoDelete | boolean | True if the server should delete the exchange when it is no longer in use (if all bindings are deleted). | false |
| | durable | boolean | A durable exchange will survive a server restart. | true |
| |===================================================================== |
| |
| You can also configure any additional `x-` arguments. |
| See details in the RabbitMQ documentation. |
| |
| |
| *Queues* |
| |
| [width="100%",cols="10%,10%,70%,10%",options="header",] |
| |===================================================================== |
| |Option |Type |Description|Default |
| | autoDelete | boolean | True if the server should delete the exchange when it is no longer in use (if all bindings are deleted). | false |
| | durable | boolean | A durable queue will survive a server restart. | false |
| | exclusive | boolean | Whether the queue is exclusive | false |
| | x-dead-letter-exchange | String | The name of the dead letter exchange. If none configured then the component configured value is used. | |
| | x-dead-letter-routing-key | String | The routing key for the dead letter exchange. If none configured then the component configured value is used. | |
| |===================================================================== |
| |
| You can also configure any additional `x-` arguments, such as the message time to live, via `x-message-ttl`, and many others. |
| See details in the RabbitMQ documentation. |
| |
| == Mapping from Camel to RabbitMQ |
| |
| The message body is mapped from Camel Message body to a `byte[]` which is the type that RabbitMQ uses for message body. |
| Camel wil use its type converter to convert the message body to byte array. |
| |
| Spring Rabbit comes out of the box with support for mapping Java serialized objects but Camel Spring RabbitMQ |
| does *not* support this due to security vulnerabilities and using Java objects is a bad design as it enforces strong coupling. |
| |
| Custom message headers is mapped from Camel Message headers to RabbitMQ headers. This behaviour can be customized by configuring |
| a new implementation of `HeaderFilterStrategy` on the Camel component. |
| |
| == Request / Reply |
| |
| Request and reply messaging is supported using https://www.rabbitmq.com/direct-reply-to.html[RabbitMQ direct reply-to]. |
| |
| The example below will do request/reply, where the message is sent via the cheese exchange name and routing key _foo.bar_, |
| which is being consumed by the 2nd Camel route, that prepends the message with `Hello `, and then sends back the message. |
| |
| So if we send `World` as message body to _direct:start_ then, we will se the message being logged |
| |
| - log:request => World |
| - log:input => World |
| - log:response => Hello World |
| |
| [source,java] |
| ---- |
| from("direct:start") |
| .to("log:request") |
| .to(ExchangePattern.InOut, "spring-rabbitmq:cheese?routingKey=foo.bar") |
| .to("log:response"); |
| |
| from("spring-rabbitmq:cheese?queues=myqueue&routingKey=foo.bar") |
| .to("log:input") |
| .transform(body().prepend("Hello ")); |
| ---- |
| |
| == Reuse endpoint and send to different destinations computed at runtime |
| |
| If you need to send messages to a lot of different RabbitMQ exchanges, it |
| makes sense to reuse a endpoint and specify the real destination in |
| a message header. This allows Camel to reuse the same endpoint, but send |
| to different exchanges. This greatly reduces the number of endpoints |
| created and economizes on memory and thread resources. |
| |
| TIP: Using xref:eips:toD-eip.adoc[toD] is easier than specifying the dynamic destination with headers |
| |
| You can specify using the following headers: |
| |
| [width="100%",cols="10%,10%,80%",options="header",] |
| |===================================================================== |
| |Header |Type |Description |
| |`CamelSpringRabbitmqExchangeOverrideName` |`String` |The exchange name. |
| |`CamelSpringRabbitmqRoutingOverrideKey` |`String` |The routing key. |
| |===================================================================== |
| |
| For example, the following route shows how you can compute a destination |
| at run time and use it to override the exchange appearing in the endpoint |
| URL: |
| |
| [source,java] |
| ---- |
| from("file://inbox") |
| .to("bean:computeDestination") |
| .to("spring-rabbitmq:dummy"); |
| ---- |
| |
| The exchange name, `dummy`, is just a placeholder. It must be provided as |
| part of the RabbitMQ endpoint URL, but it will be ignored in this example. |
| |
| In the `computeDestination` bean, specify the real destination by |
| setting the `CamelRabbitmqExchangeOverrideName` header as follows: |
| |
| [source,java] |
| ---- |
| public void setExchangeHeader(Exchange exchange) { |
| String region = .... |
| exchange.getIn().setHeader("CamelSpringRabbitmqExchangeOverrideName", "order-" + region); |
| } |
| ---- |
| |
| Then Camel will read this header and use it as the exchange name instead |
| of the one configured on the endpoint. So, in this example Camel sends |
| the message to `spring-rabbitmq:order-emea`, assuming the `region` value was `emea`. |
| |
| Keep in mind that the producer removes both `CamelSpringRabbitmqExchangeOverrideName` and `CamelSpringRabbitmqRoutingOverrideKey` |
| headers from the exchange and do not propagate them to the created Rabbitmq |
| message in order to avoid the accidental loops |
| in the routes (in scenarios when the message will be forwarded to the |
| another RabbitMQ endpoint). |
| |
| == Using toD |
| |
| If you need to send messages to a lot of different exchanges, it |
| makes sense to reuse a endpoint and specify the dynamic destinations |
| with simple language using xref:eips:toD-eip.adoc[toD]. |
| |
| For example suppose you need to send messages to exchanges with order types, |
| then using toD could for example be done as follows: |
| |
| [source,java] |
| ---- |
| from("direct:order") |
| .toD("spring-rabbit:order-${header.orderType}"); |
| ---- |
| |
| == Manual Acknowledgement |
| |
| If we need to manually acknowledge a message for some use case we can |
| do it by setting and acknowledgeMode to Manual and using the below snippet |
| of code to get Channel and deliveryTag to manually acknowledge the message: |
| |
| [source,java] |
| ---- |
| from("spring-rabbitmq:%s?queues=%s&acknowledgeMode=MANUAL") |
| .process(exchange -> { |
| Channel channel = exchange.getProperty(SpringRabbitMQConstants.CHANNEL, Channel.class); |
| long deliveryTag = exchange.getMessage().getHeader(SpringRabbitMQConstants.DELIVERY_TAG, long.class); |
| channel.basicAck(deliveryTag, false); |
| }) |
| ---- |
| |
| |
| include::spring-boot:partial$starter.adoc[] |