208 lines
42 KiB
HTML
208 lines
42 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>5. Messaging</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-aws.html" title="Spring Cloud AWS"><link rel="up" href="multi_spring-cloud-aws.html" title="Spring Cloud AWS"><link rel="prev" href="multi__managing_cloud_environments.html" title="4. Managing cloud environments"><link rel="next" href="multi__caching.html" title="6. Caching"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5. Messaging</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__managing_cloud_environments.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__caching.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_messaging" href="#_messaging"></a>5. Messaging</h1></div></div></div><p>Spring Cloud AWS provides <a class="link" href="http://aws.amazon.com/sqs/" target="_top">Amazon SQS</a> and <a class="link" href="http://aws.amazon.com/sqs/" target="_top">Amazon SNS</a> integration
|
|
that simplifies the publication and consumption of messages over SQS or SNS. While SQS fully relies on the messaging API
|
|
introduced with Spring 4.0, SNS only partially implements it as the receiving part must be handled differently for
|
|
push notifications.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_configuring_messaging" href="#_configuring_messaging"></a>5.1 Configuring messaging</h2></div></div></div><p>Before using and configuring the messaging support, the application has to include the respective module dependency
|
|
into the Maven configuration. Spring Cloud AWS Messaging support comes as a separate module to allow the modularized use
|
|
of the modules.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_maven_dependency_configuration" href="#_maven_dependency_configuration"></a>5.1.1 Maven dependency configuration</h3></div></div></div><p>The Spring Cloud AWS messaging module comes as a standalone module and can be imported with the following dependency declaration:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-aws-messaging<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>{spring-cloud-version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_sqs_support" href="#_sqs_support"></a>5.2 SQS support</h2></div></div></div><p>Amazon SQS is a hosted messaging service on the Amazon Web Service platform that provides point-to-point communication
|
|
with queues. Compared to JMS or other message services Amazon SQS has several features and limitations that should be
|
|
taken into consideration.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Amazon SQS allows only <code class="literal">String</code> payloads, so any <code class="literal">Object</code> must be transformed into a String representation.
|
|
Spring Cloud AWS has dedicated support to transfer Java objects with Amazon SQS messages by converting them to JSON.</li><li class="listitem">Amazon SQS has no transaction support, so messages might therefore be retrieved twice. Application have to be written in
|
|
an idempotent way so that they can receive a message twice.</li><li class="listitem">Amazon SQS has a maximum message size of 256kb per message, so bigger messages will fail to be sent.</li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_sending_a_message" href="#_sending_a_message"></a>5.2.1 Sending a message</h3></div></div></div><p>The <code class="literal">QueueMessagingTemplate</code> contains many convenience methods to send a message. There are send methods that specify the
|
|
destination using a <code class="literal">QueueMessageChannel</code> object and those that specify the destination using a string which is going to
|
|
be resolved against the SQS API. The send method that takes no destination argument uses the default destination.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.amazonaws.services.sqs.AmazonSQS;
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.messaging.support.MessageBuilder;
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> SqsQueueSender {
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> QueueMessagingTemplate queueMessagingTemplate;
|
|
|
|
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SqsQueueSender(AmazonSQS amazonSqs) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.queueMessagingTemplate = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> QueueMessagingTemplate(amazonSqs);
|
|
}
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> send(String message) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.queueMessagingTemplate.send(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"physicalQueueName"</span>, MessageBuilder.withPayload(message).build());
|
|
}
|
|
}</pre><p>This example uses the <code class="literal">MessageBuilder</code> class to create a message with a string payload. The <code class="literal">QueueMessagingTemplate</code> is
|
|
constructed by passing a reference to the <code class="literal">AmazonSQS</code> client. The destination in the send method is a string value that
|
|
must match the queue name defined on AWS. This value will be resolved at runtime by the Amazon SQS client. Optionally
|
|
a <code class="literal">ResourceIdResolver</code> implementation can be passed to the <code class="literal">QueueMessagingTemplate</code> constructor to resolve resources by
|
|
logical name when running inside a CloudFormation stack (see <a class="xref" href="multi__managing_cloud_environments.html" title="4. Managing cloud environments">Chapter 4, <i>Managing cloud environments</i></a> for more information about
|
|
resource name resolution).</p><p>With the messaging namespace a <code class="literal">QueueMessagingTemplate</code> can be defined in an XML configuration file.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><beans</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:xsi</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:aws-context</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/cloud/aws/context"</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns:aws-messaging</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/cloud/aws/messaging"</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xmlns</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/beans"</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">xsi:schemaLocation</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans.xsd
|
|
http://www.springframework.org/schema/cloud/aws/context
|
|
http://www.springframework.org/schema/cloud/aws/context/spring-cloud-aws-context.xsd
|
|
http://www.springframework.org/schema/cloud/aws/messaging
|
|
http://www.springframework.org/schema/cloud/aws/messaging/spring-cloud-aws-messaging"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-context:context-credentials></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-context:instance-profile-credentials /></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></aws-context:context-credentials></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:queue-messaging-template</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">id</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"queueMessagingTemplate"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></beans></span></pre><p>In this example the messaging namespace handler constructs a new <code class="literal">QueueMessagingTemplate</code>. The <code class="literal">AmazonSQS</code> client
|
|
is automatically created and passed to the template’s constructor based on the provided credentials. If the
|
|
application runs inside a configured CloudFormation stack a <code class="literal">ResourceIdResolver</code> is passed to the constructor (see
|
|
<a class="xref" href="multi__managing_cloud_environments.html" title="4. Managing cloud environments">Chapter 4, <i>Managing cloud environments</i></a> for more information about resource name resolution).</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_using_message_converters" href="#_using_message_converters"></a>Using message converters</h4></div></div></div><p>In order to facilitate the sending of domain model objects, the <code class="literal">QueueMessagingTemplate</code> has various send methods that
|
|
take a Java object as an argument for a message’s data content. The overloaded methods <code class="literal">convertAndSend()</code> and
|
|
<code class="literal">receiveAndConvert()</code> in <code class="literal">QueueMessagingTemplate</code> delegate the conversion process to an instance of the <code class="literal">MessageConverter</code>
|
|
interface. This interface defines a simple contract to convert between Java objects and SQS messages. The default
|
|
implementation <code class="literal">SimpleMessageConverter</code> simply unwraps the message payload as long as it matches the target type. By
|
|
using the converter, you and your application code can focus on the business object that is being sent or received via
|
|
SQS and not be concerned with the details of how it is represented as an SQS message.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>As SQS is only able to send <code class="literal">String</code> payloads the default converter <code class="literal">SimpleMessageConverter</code> should only be used
|
|
to send <code class="literal">String</code> payloads. For more complex objects a custom converter should be used like the one created by the
|
|
messaging namespace handler.</p></td></tr></table></div><p>It is recommended to use the XML messaging namespace to create <code class="literal">QueueMessagingTemplate</code> as it will set a more
|
|
sophisticated <code class="literal">MessageConverter</code> that converts objects into JSON when Jackson is on the classpath.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:queue-messaging-template</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">id</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"queueMessagingTemplate"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span></pre><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.queueMessagingTemplate.convertAndSend(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"queueName"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Person(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"John, "</span>Doe<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"));</span></pre><p>In this example a <code class="literal">QueueMessagingTemplate</code> is created using the messaging namespace. The <code class="literal">convertAndSend</code> method
|
|
converts the payload <code class="literal">Person</code> using the configured <code class="literal">MessageConverter</code> and sends the message.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_receiving_a_message" href="#_receiving_a_message"></a>5.2.2 Receiving a message</h3></div></div></div><p>There are two ways for receiving SQS messages, either use the <code class="literal">receive</code> methods of the <code class="literal">QueueMessagingTemplate</code> or with
|
|
annotation-driven listener endpoints. The latter is by far the more convenient way to receive messages.</p><pre class="programlisting">Person person = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.queueMessagingTemplate.receiveAndConvert(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"queueName"</span>, Person.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);</pre><p>In this example the <code class="literal">QueueMessagingTemplate</code> will get one message from the SQS queue and convert it to the target class
|
|
passed as argument.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_annotation_driven_listener_endpoints" href="#_annotation_driven_listener_endpoints"></a>5.2.3 Annotation-driven listener endpoints</h3></div></div></div><p>Annotation-driven listener endpoints are the easiest way for listening on SQS messages. Simply annotate methods with
|
|
<code class="literal">MessageMapping</code> and the <code class="literal">QueueMessageHandler</code> will route the messages to the annotated methods.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:annotation-driven-queue-listener /></span></pre><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SqsListener("queueName")</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> queueListener(Person person) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
|
}</pre><p>In this example a queue listener container is started that polls the SQS <code class="literal">queueName</code> passed to the <code class="literal">MessageMapping</code>
|
|
annotation. The incoming messages are converted to the target type and then the annotated method <code class="literal">queueListener</code> is invoked.</p><p>In addition to the payload, headers can be injected in the listener methods with the <code class="literal">@Header</code> or <code class="literal">@Headers</code>
|
|
annotations. <code class="literal">@Header</code> is used to inject a specific header value while <code class="literal">@Headers</code> injects a <code class="literal">Map<String, String></code>
|
|
containing all headers.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>It is recommended to use the XML messaging namespace to create <code class="literal">QueueMessagingTemplate</code> as it will set a more
|
|
sophisticated <code class="literal">MessageConverter</code> that converts objects into JSON when Jackson is on the classpath.</p></td></tr></table></div><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:queue-messaging-template</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">id</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"queueMessagingTemplate"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span></pre><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.queueMessagingTemplate.convertAndSend(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"queueName"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Person(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"John, "</span>Doe<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"));</span></pre><p>In this example a <code class="literal">QueueMessagingTemplate</code> is created using the messaging namespace. The <code class="literal">convertAndSend</code> method
|
|
converts the payload <code class="literal">Person</code> using the configured <code class="literal">MessageConverter</code> and sends the message.
|
|
Only the <a class="link" href="http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Message.html" target="_top">standard
|
|
message attributes</a> sent with an SQS message are supported. Custom attributes are currently not supported.</p><p>In addition to the provided argument resolvers, custom ones can be registered on the
|
|
<code class="literal">aws-messaging:annotation-driven-queue-listener</code> element using the <code class="literal">aws-messaging:argument-resolvers</code> attribute (see example below).</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:annotation-driven-queue-listener></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:argument-resolvers></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><bean</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"org.custom.CustomArgumentResolver"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></aws-messaging:argument-resolvers></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></aws-messaging:annotation-driven-queue-listener></span></pre><p>By default the <code class="literal">SimpleMessageListenerContainer</code> creates a <code class="literal">ThreadPoolTaskExecutor</code> with computed values for the core and
|
|
max pool sizes. The core pool size is set to twice the number of queues and the max pool size is obtained by multiplying
|
|
the number of queues by the value of the <code class="literal">maxNumberOfMessages</code> field. If these default values do not meet the need of
|
|
the application, a custom task executor can be set with the <code class="literal">task-executor</code> attribute (see example below).</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:annotation-driven-queue-listener</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">task-executor</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"simpleTaskExecutor"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span></pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_message_reply" href="#_message_reply"></a>Message reply</h4></div></div></div><p>Message listener methods can be annotated with <code class="literal">@SendTo</code> to send their return value to another channel. The
|
|
<code class="literal">SendToHandlerMethodReturnValueHandler</code> uses the defined messaging template set on the
|
|
<code class="literal">aws-messaging:annotation-driven-queue-listener</code> element to send the return value. The messaging template must implement
|
|
the <code class="literal">DestinationResolvingMessageSendingOperations</code> interface.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:annotation-driven-queue-listener</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">send-to-message-template</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"queueMessagingTemplate"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/></span></pre><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SqsListener("treeQueue")</span></em>
|
|
<em><span class="hl-annotation" style="color: gray">@SendTo("leafsQueue")</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> List<Leaf> extractLeafs(Tree tree) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
|
}</pre><p>In this example the <code class="literal">extractLeafs</code> method will receive messages coming from the <code class="literal">treeQueue</code> and then return a
|
|
<code class="literal">List</code> of <code class="literal">Leaf</code>s which is going to be sent to the <code class="literal">leafsQueue</code>. Note that on the
|
|
<code class="literal">aws-messaging:annotation-driven-queue-listener</code> XML element there is an attribute <code class="literal">send-to-message-template</code>
|
|
that specifies <code class="literal">QueueMessagingTemplate</code> as the messaging template to be used to send the return value of the message
|
|
listener method.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_the_simplemessagelistenercontainerfactory" href="#_the_simplemessagelistenercontainerfactory"></a>5.2.4 The SimpleMessageListenerContainerFactory</h3></div></div></div><p>The <code class="literal">SimpleMessageListenerContainer</code> can also be configured with Java by creating a bean of type <code class="literal">SimpleMessageListenerContainerFactory</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory(AmazonSQSAsync amazonSqs) {
|
|
SimpleMessageListenerContainerFactory factory = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SimpleMessageListenerContainerFactory();
|
|
factory.setAmazonSqs(amazonSqs);
|
|
factory.setAutoStartup(false);
|
|
factory.setMaxNumberOfMessages(<span class="hl-number">5</span>);
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory;
|
|
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consuming_aws_event_messages_with_amazon_sqs" href="#_consuming_aws_event_messages_with_amazon_sqs"></a>5.2.5 Consuming AWS Event messages with Amazon SQS</h3></div></div></div><p>It is also possible to receive AWS generated event messages with the SQS message listeners. Because
|
|
AWS messages does not contain the mime-type header, the Jackson message converter has to be configured
|
|
with the <code class="literal">strictContentTypeMatch</code> property false to also parse message without the proper mime type.</p><p>The next code shows the configuration of the message converter using the <code class="literal">QueueMessageHandlerFactory</code>
|
|
and re-configuring the <code class="literal">MappingJackson2MessageConverter</code></p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> QueueMessageHandlerFactory queueMessageHandlerFactory() {
|
|
QueueMessageHandlerFactory factory = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> QueueMessageHandlerFactory();
|
|
MappingJackson2MessageConverter messageConverter = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> MappingJackson2MessageConverter();
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//set strict content type match to false</span>
|
|
messageConverter.setStrictContentTypeMatch(false);
|
|
factory.setArgumentResolvers(Collections.<HandlerMethodArgumentResolver>singletonList(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> PayloadArgumentResolver(messageConverter)));
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory;
|
|
}</pre><p>With the configuration above, it is possible to receive event notification for S3 buckets (and also other
|
|
event notifications like elastic transcoder messages) inside <code class="literal">@SqsListener</code> annotated methods s shown below.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SqsListener("testQueue")</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> receive(S3EventNotification s3EventNotificationRecord) {
|
|
S3EventNotification.S3Entity s3Entity = s3EventNotificationRecord.getRecords().get(<span class="hl-number">0</span>).getS3();
|
|
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_sns_support" href="#_sns_support"></a>5.3 SNS support</h2></div></div></div><p>Amazon SNS is a publish-subscribe messaging system that allows clients to publish notification to a particular topic. Other
|
|
interested clients may subscribe using different protocols like HTTP/HTTPS, e-mail or an Amazon SQS queue to receive the messages.</p><p>The next graphic shows a typical example of an Amazon SNS architecture.</p><div class="informalfigure"><div class="mediaobject"><img src="images/sns-overview.png" alt="SNS Overview"></div></div><p>Spring Cloud AWS supports Amazon SNS by providing support to send notifications with a <code class="literal">NotificationMessagingTemplate</code> and
|
|
to receive notifications with the HTTP/HTTPS endpoint using the Spring Web MVC <code class="literal">@Controller</code> based programming model. Amazon
|
|
SQS based subscriptions can be used with the annotation-driven message support that is provided by the Spring Cloud AWS messaging module.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_sending_a_message_2" href="#_sending_a_message_2"></a>5.3.1 Sending a message</h3></div></div></div><p>The <code class="literal">NotificationMessagingTemplate</code> contains two convenience methods to send a notification. The first one specifies the
|
|
destination using a <code class="literal">String</code> which is going to be resolved against the SNS API. The second one takes no destination
|
|
argument and uses the default destination. All the usual send methods that are available on the <code class="literal">MessageSendingOperations</code>
|
|
are implemented but are less convenient to send notifications because the subject must be passed as header.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Currently only <code class="literal">String</code> payloads can be sent using the <code class="literal">NotificationMessagingTemplate</code> as this is the expected
|
|
type by the SNS API.</p></td></tr></table></div><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.amazonaws.services.sns.AmazonSNS;
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.aws.messaging.core.NotificationMessagingTemplate;
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> SnsNotificationSender {
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> NotificationMessagingTemplate notificationMessagingTemplate;
|
|
|
|
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SnsNotificationSender(AmazonSNS amazonSns) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.notificationMessagingTemplate = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> NotificationMessagingTemplate(amazonSns);
|
|
}
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> send(String subject, String message) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.notificationMessagingTemplate.sendNotification(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"physicalTopicName"</span>, message, subject);
|
|
}
|
|
}</pre><p>This example constructs a new <code class="literal">NotificationMessagingTemplate</code> by passing an <code class="literal">AmazonSNS</code> client as argument. In the <code class="literal">send</code>
|
|
method the convenience <code class="literal">sendNotification</code> method is used to send a <code class="literal">message</code> with <code class="literal">subject</code> to an SNS topic. The
|
|
destination in the <code class="literal">sendNotification</code> method is a string value that must match the topic name defined on AWS. This value
|
|
is resolved at runtime by the Amazon SNS client. Optionally a <code class="literal">ResourceIdResolver</code> implementation can be passed to the
|
|
<code class="literal">NotificationMessagingTemplate</code> constructor to resolve resources by logical name when running inside a CloudFormation stack.
|
|
(See <a class="xref" href="multi__managing_cloud_environments.html" title="4. Managing cloud environments">Chapter 4, <i>Managing cloud environments</i></a> for more information about resource name resolution.)</p><p>It is recommended to use the XML messaging namespace to create <code class="literal">NotificationMessagingTemplate</code> as it will automatically
|
|
configure the SNS client to setup the default converter.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:notification-messaging-template</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">id</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"notificationMessagingTemplate"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_annotation_driven_http_notification_endpoint" href="#_annotation_driven_http_notification_endpoint"></a>5.3.2 Annotation-driven HTTP notification endpoint</h3></div></div></div><p>SNS supports multiple endpoint types (SQS, Email, HTTP, HTTPS), Spring Cloud AWS provides support for HTTP(S) endpoints.
|
|
SNS sends three type of requests to an HTTP topic listener endpoint, for each of them annotations are provided:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Subscription request → <code class="literal">@NotificationSubscriptionMapping</code></li><li class="listitem">Notification request → <code class="literal">@NotificationMessageMapping</code></li><li class="listitem">Unsubscription request → <code class="literal">@NotificationUnsubscribeMapping</code></li></ul></div><p>HTTP endpoints are based on Spring MVC controllers. Spring Cloud AWS added some custom argument resolvers to extract
|
|
the message and subject out of the notification requests.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Controller</span></em>
|
|
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/topicName")</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> NotificationTestController {
|
|
|
|
<em><span class="hl-annotation" style="color: gray">@NotificationSubscriptionMapping</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> handleSubscriptionMessage(NotificationStatus status) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> IOException {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//We subscribe to start receive the message</span>
|
|
status.confirmSubscription();
|
|
}
|
|
|
|
<em><span class="hl-annotation" style="color: gray">@NotificationMessageMapping</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> handleNotificationMessage(<em><span class="hl-annotation" style="color: gray">@NotificationSubject</span></em> String subject, <em><span class="hl-annotation" style="color: gray">@NotificationMessage</span></em> String message) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
|
}
|
|
|
|
<em><span class="hl-annotation" style="color: gray">@NotificationUnsubscribeConfirmationMapping</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> handleUnsubscribeMessage(NotificationStatus status) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//e.g. the client has been unsubscribed and we want to "re-subscribe"</span>
|
|
status.confirmSubscription();
|
|
}
|
|
}</pre><div class="caution" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Caution"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="images/caution.png"></td><th align="left">Caution</th></tr><tr><td align="left" valign="top"><p>Currently it is not possible to define the mapping URL on the method level therefore the <code class="literal">RequestMapping</code> must
|
|
be done at type level and must contain the full path of the endpoint.</p></td></tr></table></div><p>This example creates a new Spring MVC controller with three methods to handle the three requests listed above. In order
|
|
to resolve the arguments of the <code class="literal">handleNotificationMessage</code> methods a custom argument resolver must be registered. The
|
|
XML configuration is listed below.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><mvc:annotation-driven></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><mvc:argument-resolvers></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><ref</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">bean</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"notificationResolver"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></mvc:argument-resolvers></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></mvc:annotation-driven></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:notification-argument-resolver</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">id</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"notificationResolver"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span></pre><p>The <code class="literal">aws-messaging:notification-argument-resolver</code> element registers three argument resolvers:
|
|
<code class="literal">NotificationStatusHandlerMethodArgumentResolver</code>, <code class="literal">NotificationMessageHandlerMethodArgumentResolver</code>,
|
|
and <code class="literal">NotificationSubjectHandlerMethodArgumentResolver</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_cloudformation" href="#_using_cloudformation"></a>5.4 Using CloudFormation</h2></div></div></div><p>Amazon SQS queues and SNS topics can be configured within a stack and then be used by applications. Spring Cloud AWS
|
|
also supports the lookup of stack-configured queues and topics by their logical name with the resolution to the physical
|
|
name. The example below shows an SNS topic and SQS queue configuration inside a CloudFormation template.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"LogicalQueueName"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"AWS::SQS::Queue"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Properties"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"LogicalTopicName"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"AWS::SNS::Topic"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Properties"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>The logical names <code class="literal">LogicalQueueName</code> and <code class="literal">LogicalTopicName</code> can then be used in the configuration and in the application
|
|
as shown below:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:queue-messaging-template</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">default-destination</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"LogicalQueueName"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span>
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><aws-messaging:notification-messaging-template</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">default-destination</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"LogicalTopicName"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"> /></span></pre><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SqsListener("LogicalQueueName")</span></em>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> receiveQueueMessages(Person person) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Logical names can also be used with messaging templates</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.notificationMessagingTemplate.sendNotification(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"anotherLogicalTopicName"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Message"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Subject"</span>);
|
|
}</pre><p>When using the logical names like in the example above, the stack can be created on different environments without any
|
|
configuration or code changes inside the application.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__managing_cloud_environments.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__caching.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Managing cloud environments </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-aws.html">Home</a></td><td width="40%" align="right" valign="top"> 6. Caching</td></tr></table></div></body></html> |