INTEXT-147: Add SnsInboundChannelAdapter
JIRA: https://jira.spring.io/browse/INTEXT-147 INTEXT-147: Documentation Upgrade dependencies
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int-aws="http://www.springframework.org/schema/integration/aws"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/aws http://www.springframework.org/schema/integration/aws/spring-integration-aws.xsd">
|
||||
|
||||
<bean id="amazonSns" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="com.amazonaws.services.sns.AmazonSNS"/>
|
||||
</bean>
|
||||
|
||||
<int-aws:sns-inbound-channel-adapter sns="amazonSns"
|
||||
path="/foo"
|
||||
auto-startup="false"
|
||||
channel="errorChannel"
|
||||
error-channel="nullChannel"
|
||||
phase="100"
|
||||
id="snsInboundChannelAdapter"
|
||||
send-timeout="2000"
|
||||
handle-notification-status="true"
|
||||
payload-expression="payload.Message"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.aws.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.integration.aws.inbound.SnsInboundChannelAdapter;
|
||||
import org.springframework.integration.channel.NullChannel;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.amazonaws.services.sns.AmazonSNS;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class SnsInboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired
|
||||
private AmazonSNS amazonSns;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel errorChannel;
|
||||
|
||||
@Autowired
|
||||
private NullChannel nullChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("snsInboundChannelAdapter")
|
||||
private SnsInboundChannelAdapter snsInboundChannelAdapter;
|
||||
|
||||
|
||||
@Test
|
||||
public void testSqsMessageDrivenChannelAdapterParser() {
|
||||
assertSame(this.amazonSns, TestUtils.getPropertyValue(this.snsInboundChannelAdapter,
|
||||
"notificationStatusResolver.amazonSns"));
|
||||
assertTrue(TestUtils.getPropertyValue(this.snsInboundChannelAdapter, "handleNotificationStatus", Boolean.class));
|
||||
assertArrayEquals(new String[] {"/foo"},
|
||||
TestUtils.getPropertyValue(this.snsInboundChannelAdapter, "requestMapping.pathPatterns", String[].class));
|
||||
assertEquals("payload.Message",
|
||||
TestUtils.getPropertyValue(this.snsInboundChannelAdapter, "payloadExpression.expression"));
|
||||
assertFalse(this.snsInboundChannelAdapter.isRunning());
|
||||
assertEquals(100, this.snsInboundChannelAdapter.getPhase());
|
||||
assertFalse(this.snsInboundChannelAdapter.isAutoStartup());
|
||||
assertSame(this.errorChannel, TestUtils.getPropertyValue(this.snsInboundChannelAdapter, "requestChannel"));
|
||||
assertSame(this.nullChannel, TestUtils.getPropertyValue(this.snsInboundChannelAdapter, "errorChannel"));
|
||||
assertEquals(2000L, TestUtils.getPropertyValue(this.snsInboundChannelAdapter, "messagingTemplate.sendTimeout"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:aws-messaging="http://www.springframework.org/schema/cloud/aws/messaging"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/aws http://www.springframework.org/schema/integration/aws/spring-integration-aws.xsd
|
||||
http://www.springframework.org/schema/cloud/aws/messaging http://www.springframework.org/schema/cloud/aws/messaging/spring-cloud-aws-messaging-1.0.xsd">
|
||||
http://www.springframework.org/schema/cloud/aws/messaging http://www.springframework.org/schema/cloud/aws/messaging/spring-cloud-aws-messaging.xsd">
|
||||
|
||||
<aws-messaging:sqs-async-client id="sqs"/>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:aws-messaging="http://www.springframework.org/schema/cloud/aws/messaging"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/aws http://www.springframework.org/schema/integration/aws/spring-integration-aws.xsd
|
||||
http://www.springframework.org/schema/cloud/aws/messaging http://www.springframework.org/schema/cloud/aws/messaging/spring-cloud-aws-messaging-1.0.xsd">
|
||||
http://www.springframework.org/schema/cloud/aws/messaging http://www.springframework.org/schema/cloud/aws/messaging/spring-cloud-aws-messaging.xsd">
|
||||
|
||||
<aws-messaging:sqs-async-client id="sqs"/>
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.aws.inbound;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.aws.messaging.endpoint.NotificationStatus;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.integration.aws.support.AwsHeaders;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.amazonaws.services.sns.AmazonSNS;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
@DirtiesContext
|
||||
public class SnsInboundChannelAdapterTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private AmazonSNS amazonSns;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel inputChannel;
|
||||
|
||||
@Value("classpath:org/springframework/integration/aws/inbound/subscriptionConfirmation.json")
|
||||
private Resource subscriptionConfirmation;
|
||||
|
||||
@Value("classpath:org/springframework/integration/aws/inbound/notificationMessage.json")
|
||||
private Resource notificationMessage;
|
||||
|
||||
@Value("classpath:org/springframework/integration/aws/inbound/unsubscribeConfirmation.json")
|
||||
private Resource unsubscribeConfirmation;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionConfirmation() throws Exception {
|
||||
this.mockMvc.perform(
|
||||
post("/mySampleTopic")
|
||||
.header("x-amz-sns-message-type", "SubscriptionConfirmation")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(StreamUtils.copyToByteArray(this.subscriptionConfirmation.getInputStream())))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
Message<?> receive = inputChannel.receive(10000);
|
||||
assertNotNull(receive);
|
||||
assertTrue(receive.getHeaders().containsKey(AwsHeaders.SNS_MESSAGE_TYPE));
|
||||
assertEquals("SubscriptionConfirmation", receive.getHeaders().get(AwsHeaders.SNS_MESSAGE_TYPE));
|
||||
|
||||
assertTrue(receive.getHeaders().containsKey(AwsHeaders.NOTIFICATION_STATUS));
|
||||
NotificationStatus notificationStatus = (NotificationStatus) receive.getHeaders()
|
||||
.get(AwsHeaders.NOTIFICATION_STATUS);
|
||||
|
||||
notificationStatus.confirmSubscription();
|
||||
|
||||
verify(this.amazonSns)
|
||||
.confirmSubscription("arn:aws:sns:eu-west-1:111111111111:mySampleTopic", "111");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testNotification() throws Exception {
|
||||
this.mockMvc.perform(
|
||||
post("/mySampleTopic")
|
||||
.header("x-amz-sns-message-type", "Notification")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(StreamUtils.copyToByteArray(this.notificationMessage.getInputStream())))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
Message<?> receive = inputChannel.receive(10000);
|
||||
assertNotNull(receive);
|
||||
Map<String, String> payload = (Map<String, String>) receive.getPayload();
|
||||
|
||||
assertEquals("foo", payload.get("Subject"));
|
||||
assertEquals("bar", payload.get("Message"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsubscribe() throws Exception {
|
||||
this.mockMvc.perform(
|
||||
post("/mySampleTopic")
|
||||
.header("x-amz-sns-message-type", "UnsubscribeConfirmation")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(StreamUtils.copyToByteArray(this.unsubscribeConfirmation.getInputStream())))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
Message<?> receive = inputChannel.receive(10000);
|
||||
assertNotNull(receive);
|
||||
assertTrue(receive.getHeaders().containsKey(AwsHeaders.SNS_MESSAGE_TYPE));
|
||||
assertEquals("UnsubscribeConfirmation", receive.getHeaders().get(AwsHeaders.SNS_MESSAGE_TYPE));
|
||||
|
||||
assertTrue(receive.getHeaders().containsKey(AwsHeaders.NOTIFICATION_STATUS));
|
||||
NotificationStatus notificationStatus = (NotificationStatus) receive.getHeaders()
|
||||
.get(AwsHeaders.NOTIFICATION_STATUS);
|
||||
|
||||
notificationStatus.confirmSubscription();
|
||||
|
||||
verify(this.amazonSns)
|
||||
.confirmSubscription("arn:aws:sns:eu-west-1:111111111111:mySampleTopic", "233");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
public static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public AmazonSNS amazonSns() {
|
||||
return Mockito.mock(AmazonSNS.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PollableChannel inputChannel() {
|
||||
return new QueueChannel();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HttpRequestHandler sqsMessageDrivenChannelAdapter() {
|
||||
SnsInboundChannelAdapter adapter = new SnsInboundChannelAdapter(amazonSns(), "/mySampleTopic");
|
||||
adapter.setRequestChannel(inputChannel());
|
||||
adapter.setHandleNotificationStatus(true);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"Type": "Notification",
|
||||
"MessageId": "f2c15fec-c617-5b08-b54d-13c4099fec60",
|
||||
"TopicArn": "arn:aws:sns:eu-west-1:111111111111:mySampleTopic",
|
||||
"Subject": "foo",
|
||||
"Message": "bar",
|
||||
"Timestamp": "2014-06-28T14:12:24.418Z",
|
||||
"SignatureVersion": "1",
|
||||
"Signature": "XDvKSAnhxECrAmyIrs0Dsfbp/tnKD1IvoOOYTU28FtbUoxr/CgziuW87yZwTuSNNbHJbdD3BEjHS0vKewm0xBeQ0PToDkgtoORXo5RWnmShDQ2nhkthFhZnNulKtmFtRogjBtCwbz8sPnbOCSk21ruyXNdV2RUbdDalndAW002CWEQmYMxFSN6OXUtMueuT610aX+tqeYP4Z6+8WTWLWjAuVyy7rOI6KHYBcVDhKtskvTOPZ4tiVohtQdQbO2Gjuh1vblRzzwMkfaoFTSWImd4pFXxEsv/fq9aGIlqq9xEryJ0w2huFwI5gxyhvGt0RnTd9YvmAEC+WzdJDOqaDNxg==",
|
||||
"SigningCertURL": "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-e372f8ca30337fdb084e8ac449342c77.pem",
|
||||
"UnsubscribeURL": "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:721324560415:mySampleTopic:9859a6c9-6083-4690-ab02-d1aead3442df",
|
||||
"MessageAttributes": {
|
||||
"AWS.SNS.MOBILE.MPNS.Type": {
|
||||
"Type": "String",
|
||||
"Value": "token"
|
||||
},
|
||||
"AWS.SNS.MOBILE.WNS.Type": {
|
||||
"Type": "String",
|
||||
"Value": "wns/badge"
|
||||
},
|
||||
"AWS.SNS.MOBILE.MPNS.NotificationClass": {
|
||||
"Type": "String",
|
||||
"Value": "realtime"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Type": "SubscriptionConfirmation",
|
||||
"MessageId": "e267b24c-5532-472f-889d-c2cdd2143bbc",
|
||||
"Token": "111",
|
||||
"TopicArn": "arn:aws:sns:eu-west-1:111111111111:mySampleTopic",
|
||||
"Message": "You have chosen to subscribe to the topic arn:aws:sns:eu-west-1:721324560415:mySampleTopic.To confirm the subscription, visit the SubscribeURL included in this message.",
|
||||
"SubscribeURL": "https://sns.eu-west-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:eu-west-1:111111111111:mySampleTopic&Token=111",
|
||||
"Timestamp": "2014-06-28T10:22:18.086Z",
|
||||
"SignatureVersion": "1",
|
||||
"Signature": "JLdRUR+uhP4cyVW6bRuUSAkUosFMJyO7g7WCAwEUJoB4y8vQE1uDUWGpbQSEbruVTjPEM8hFsf4/95NftfM0W5IgND1uSnv4P/4AYyL+q0bLOJlquzXrw4w2NX3QShS3y+r/gXzo7p/UP4NOr35MGCEGPqHAEe1Coc5S0eaP3JvKU6xY1tcop6ze2RNHTwzhM43dda2bnjPYogAJzA5uHfmSjs3cMVvPCckj3zdLyvxISp+RgrogdvlNyu9ycND1SxagmbzjkBaqvF/4aiSYFxsEXX4e9zuNuHGmXGWgm1ppYUGLSPPJruCsPUa7Ii1mYvpX7SezuFZlAAXXBk0mHg==",
|
||||
"SigningCertURL": "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-e372f8ca30337fdb084e8ac449342c77.pem"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Type": "UnsubscribeConfirmation",
|
||||
"MessageId": "7b9a6321-45d5-461a-bc35-9c2d18ed9dbe",
|
||||
"Token": "233",
|
||||
"TopicArn": "arn:aws:sns:eu-west-1:111111111111:mySampleTopic",
|
||||
"Message": "You have chosen to deactivate subscription arn:aws:sns:eu-west-1:111111111111:mySampleTopic:f64111de-e681-4820-a8be-474f64c1bbf8.\nTo cancel this operation and restore the subscription, visit the SubscribeURL included in this message.",
|
||||
"SubscribeURL": "https://sns.eu-west-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:eu-west-1:721324560415:mySampleTopic&Token=233",
|
||||
"Timestamp": "2014-06-28T19:33:00.497Z",
|
||||
"SignatureVersion": "1",
|
||||
"Signature": "EAb0k1XoD2h+u4j2GB42wEFCVUFKEaS/2W+p+3wK1GfZDZn4LeDLbkxJ1LYF/A1CYL+sCJ4ZmLFI1axm0V/p+fESkNbKQoQotMgma+PtA6KnmRrKEU8O6nUELqeVPWFAoQ9ZsW9FCAXVDXoPxiqHNTH+tC7mzAsvajyp4aTm/POqkRKBl+A/7dHUqfHGup/FJhLNgTAciBZSloa5EuBKxInJQfoZjy3DU8qKXXhmKKRdyVwOGEuReo/njy4c3Phtn0+logu2PZUKqkGTuJZVbapHmcTq+0MqIh05sevLDmTEfBlsmNThhWIyCza/t68RRlqm9cRLjINSWfrv1Xkrpw==",
|
||||
"SigningCertURL": "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-e372f8ca30337fdb084e8ac449342c77.pem"
|
||||
}
|
||||
Reference in New Issue
Block a user