Files
spring-cloud-static/spring-cloud-aws/2.0.0.M2/multi/multi__messaging.html
2017-11-17 04:34:49 +00:00

208 lines
42 KiB
HTML

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>5.&nbsp;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.&nbsp;Managing cloud environments"><link rel="next" href="multi__caching.html" title="6.&nbsp;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.&nbsp;Messaging</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__managing_cloud_environments.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<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.&nbsp;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&nbsp;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&nbsp;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">&lt;dependency&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;groupId&gt;</span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/groupId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;artifactId&gt;</span>spring-cloud-aws-messaging<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/artifactId&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;version&gt;</span>{spring-cloud-version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/version&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/dependency&gt;</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&nbsp;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&nbsp;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.&nbsp;Managing cloud environments">Chapter&nbsp;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">&lt;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">&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;aws-context:context-credentials&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;aws-context:instance-profile-credentials /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/aws-context:context-credentials&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;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"> /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/beans&gt;</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&#8217;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.&nbsp;Managing cloud environments">Chapter&nbsp;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&#8217;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">&lt;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"> /&gt;</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&nbsp;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&nbsp;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">&lt;aws-messaging:annotation-driven-queue-listener /&gt;</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&lt;String, String&gt;</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">&lt;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"> /&gt;</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">&lt;aws-messaging:annotation-driven-queue-listener&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;aws-messaging:argument-resolvers&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;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"> /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/aws-messaging:argument-resolvers&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/aws-messaging:annotation-driven-queue-listener&gt;</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">&lt;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"> /&gt;</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">&lt;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">/&gt;</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&lt;Leaf&gt; 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&nbsp;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&nbsp;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.&lt;HandlerMethodArgumentResolver&gt;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&nbsp;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&nbsp;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.&nbsp;Managing cloud environments">Chapter&nbsp;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">&lt;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"> /&gt;</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&nbsp;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 &#8594; <code class="literal">@NotificationSubscriptionMapping</code></li><li class="listitem">Notification request &#8594; <code class="literal">@NotificationMessageMapping</code></li><li class="listitem">Unsubscription request &#8594; <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">&lt;mvc:annotation-driven&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;mvc:argument-resolvers&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;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"> /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/mvc:argument-resolvers&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;/mvc:annotation-driven&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;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"> /&gt;</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&nbsp;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">&lt;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"> /&gt;</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">&lt;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"> /&gt;</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>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__caching.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4.&nbsp;Managing cloud environments&nbsp;</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">&nbsp;6.&nbsp;Caching</td></tr></table></div></body></html>