diff --git a/src/reference/docbook/amqp.xml b/src/reference/docbook/amqp.xml index bac265a7..81c9c58d 100644 --- a/src/reference/docbook/amqp.xml +++ b/src/reference/docbook/amqp.xml @@ -584,6 +584,16 @@ public AmqpTemplate rabbitTemplate(); RabbitTemplate. +
+ Messaging integration + + Starting with version 1.4 RabbitMessagingTemplate, built on top of + RabbitTemplate, provides an integration with the + Spring Framework messaging abstraction, i.e. + org.springframework.messaging.Message. This allows you to create the message to send + in generic manner. + +
@@ -876,14 +886,23 @@ if (received) { }]]>
-
Asynchronous ConsumerFor asynchronous Message +
Asynchronous Consumer + + + Spring AMQP also supports annotated-listener endpoints through the use of the + @RabbitListener annotation and provides an open infrastructure to register endpoints + programmatically. This is by far the most convenient way to setup an asynchronous consumer, see + for more details. + + + For asynchronous Message reception, a dedicated component (not the AmqpTemplate) is involved. That component is a container for a Message consuming callback. We will look at the container and its properties in just a moment, but first we should look at the callback since that is where your application code will be integrated - with the messaging system. There are a few options for the callback. The - simplest of these is to implement the + with the messaging system. There are a few options for the callback + starting with an implementation of the MessageListener interface: - + + + You can subclass the adapter and provide an implementation of getListenerMethodName() + to dynamically select different methods based on the message. + Now that you've seen the various options for the Message-listening callback, @@ -1023,7 +1047,205 @@ container.setConsumerArguments(Collections. singletonMap("x-pri same reason. When the container is later started, it uses it's reference to containerAdmin to declare the elements. -
+
+ +
+ Annotation-driven listener endpoints + + Starting with version 1.4, + the easiest way to receive a message asynchronously is to use the annotated listener + endpoint infrastructure. In a nutshell, it allows you to expose a method of a managed bean + as a Rabbit listener endpoint. + + The idea of the example above is that, whenever a message is available on the + org.springframework.amqp.core.Queue "myQueue", the processOrder + method is invoked accordingly (in this case, with the payload of the message). + + The annotated endpoint infrastructure creates a message listener container behind the scenes + for each annotated method, using a RabbitListenerContainerFactory. + +
+ Enable listener endpoint annotations + + To enable support for @RabbitListener annotations add + @EnableRabbit to one of your @Configuration classes. + + By default, the infrastructure looks for a bean named rabbitListenerContainerFactory + as the source for the factory to use to create message listener containers. In this case, and ignoring the + RabbitMQ infrastructure setup, the processOrder method can be invoked with a core + poll size of 3 threads and a maximum pool size of 10 threads. + + It is possible to customize the listener container factory to use per annotation or an explicit + default can be configured by implementing the RabbitListenerConfigurer + interface. The default is only required if at least one endpoint is registered without a specific container + factory. See the javadoc for full details and examples. + + If you prefer XML configuration, use the <rabbit:annotation-driven> element. + + + + + + + +]]> +
+
+ Programmatic Endpoint Registration + + RabbitListenerEndpoint provides a model of a Rabbit endpoint and is + responsible for configuring the container for that model. The infrastructure allows you to + configure endpoints programmatically in addition to the ones that are detected by the + RabbitListener annotation. { + // processing + }); + registrar.registerEndpoint(endpoint); + } +}]]> + In the example above, we used SimpleRabbitListenerEndpoint which provides + the actual MessageListener to invoke but you could just as well build your own + endpoint variant describing a custom invocation mechanism. + + It should be noted that you could just as well skip the use of @RabbitListener + altogether and only register your endpoints programmatically through RabbitListenerConfigurer. +
+
+ Annotated Endpoint Method Signature + + So far, we have been injecting a simple String in our endpoint but it can actually have a very + flexible method signature. Let’s rewrite it to inject the Order with a custom header: + + These are the main elements you can inject in listener endpoints: + + + The raw org.springframework.amqp.core.Message. + + + The com.rabbitmq.client.Channel on which the message was received + + + The org.springframework.messaging.Message representing the incoming AMQP + message. Note that this message holds both the custom and the standard headers (as defined + by AmqpHeaders). + + + @Header-annotated method arguments to extract a specific header value, + including standard AMQP headers. + + + @Headers-annotated argument that must also be assignable to + java.util.Map for getting access to all headers. + + + A non-annotated element that is not one of the supported types (i.e. Message + and Channel) is considered to be the payload. You can make that explicit by + annotating the parameter with @Payload. You can also turn on validation by + adding an extra @Valid. + + + + The ability to inject Spring’s Message abstraction is particularly useful to benefit from all + the information stored in the transport-specific message without relying on transport-specific API. + order) { ... } +]]> + + Handling of method arguments is provided by DefaultMessageHandlerMethodFactory + which can be further customized to support additional method arguments. The conversion and validation + support can be customized there as well. + + For instance, if we want to make sure our Order is valid before processing it, we can annotate + the payload with @Valid and configure the necessary validator as follows: + +
+
+ Reply Management + The existing support in MessageListenerAdapter already allows your method to + have a non-void return type. When that’s the case, the result of the invocation is encapsulated in a + message sent either in the address specified in the ReplyToAddress header of + the original message or in the default address configured on the listener. That default address can + now be set using the @SendTo annotation of the messaging abstraction. + + Assuming our processOrder method should now return an + OrderStatus, it is possible to write it as follow to automatically send a reply: + + If you need to set additional headers in a transport-independent manner, you could return a + Message instead, something like: processOrder(Order order) { + // order processing + return MessageBuilder + .withPayload(status) + .setHeader("code", 1234) + .build(); +}]]> +
diff --git a/src/reference/docbook/index.xml b/src/reference/docbook/index.xml index 0eca8511..f8560cd3 100644 --- a/src/reference/docbook/index.xml +++ b/src/reference/docbook/index.xml @@ -43,6 +43,14 @@ Gunnar Hillert + + Artem + Bilan + + + Stephane + Nicoll + 2010-2014 diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml index 503ffdf0..de2b0a52 100644 --- a/src/reference/docbook/whats-new.xml +++ b/src/reference/docbook/whats-new.xml @@ -11,7 +11,7 @@ POJO listeners can be annotated with @RabbitListener, enabled by @EnableRabbit or <rabbit:annotation-driven />. Spring Framework 4.1 is required for this feature. - More documentation to follow. + See for more information.
@@ -22,7 +22,7 @@ It uses the RabbitTemplate internally which can be configured as normal. Spring Framework 4.1 is required for this feature. - More documentation to follow. + See for more information.