/* * Copyright 2013-2014 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.cloud.aws.messaging.config.annotation; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; import com.amazonaws.services.sqs.AmazonSQSAsync; import com.amazonaws.services.sqs.AmazonSQSAsyncClient; import com.amazonaws.services.sqs.buffered.AmazonSQSBufferedAsyncClient; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.cloud.aws.context.config.annotation.EnableContextRegion; import org.springframework.cloud.aws.core.env.ResourceIdResolver; import org.springframework.cloud.aws.messaging.config.QueueMessageHandlerFactory; import org.springframework.cloud.aws.messaging.config.SimpleMessageListenerContainerFactory; import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate; import org.springframework.cloud.aws.messaging.listener.QueueMessageHandler; import org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer; import org.springframework.cloud.aws.messaging.support.destination.DynamicQueueUrlDestinationResolver; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.messaging.core.DestinationResolver; import org.springframework.messaging.core.DestinationResolvingMessageSendingOperations; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler; import org.springframework.test.util.ReflectionTestUtils; import java.util.Collections; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; /** * @author Alain Sahli */ public class SqsConfigurationTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void configuration_withMinimalBeans_shouldStartSqsListenerContainer() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MinimalConfiguration.class); SimpleMessageListenerContainer container = applicationContext.getBean(SimpleMessageListenerContainer.class); // Assert assertTrue(container.isRunning()); QueueMessageHandler queueMessageHandler = applicationContext.getBean(QueueMessageHandler.class); assertTrue(QueueMessageHandler.class.isInstance(queueMessageHandler)); HandlerMethodReturnValueHandler sendToReturnValueHandler = queueMessageHandler.getCustomReturnValueHandlers().get(0); QueueMessagingTemplate messagingTemplate = (QueueMessagingTemplate) ReflectionTestUtils.getField(sendToReturnValueHandler, "messageTemplate"); AmazonSQSBufferedAsyncClient amazonBufferedSqsClient = (AmazonSQSBufferedAsyncClient) ReflectionTestUtils.getField(messagingTemplate, "amazonSqs"); AmazonSQSAsyncClient amazonSqsClient = (AmazonSQSAsyncClient) ReflectionTestUtils.getField(amazonBufferedSqsClient, "realSQS"); assertNotNull(ReflectionTestUtils.getField(amazonSqsClient, "awsCredentialsProvider")); } @Test public void configuration_withCustomAmazonClient_shouldBeUsedByTheContainer() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationWithCustomAmazonClient.class); // Assert AmazonSQSAsync amazonSqsClient = applicationContext.getBean(AmazonSQSAsync.class); assertEquals(ConfigurationWithCustomAmazonClient.CUSTOM_SQS_CLIENT, amazonSqsClient); } @Test public void messageHandler_withFactoryConfiguration_shouldUseCustomValues() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationWithCustomizedMessageHandler.class); QueueMessageHandler messageHandler = applicationContext.getBean(QueueMessageHandler.class); // Assert assertEquals(1, messageHandler.getCustomArgumentResolvers().size()); assertEquals(ConfigurationWithCustomizedMessageHandler.CUSTOM_ARGUMENT_RESOLVER, messageHandler.getCustomArgumentResolvers().get(0)); assertEquals(2, messageHandler.getCustomReturnValueHandlers().size()); assertEquals(ConfigurationWithCustomizedMessageHandler.CUSTOM_RETURN_VALUE_HANDLER, messageHandler.getCustomReturnValueHandlers().get(0)); Object sendToMessageTemplate = ReflectionTestUtils.getField(messageHandler.getReturnValueHandlers().get(1), "messageTemplate"); assertEquals(ConfigurationWithCustomizedMessageHandler.CUSTOM_AMAZON_SQS, ReflectionTestUtils.getField(sendToMessageTemplate, "amazonSqs")); Object destinationResolver = ReflectionTestUtils.getField(sendToMessageTemplate, "destinationResolver"); Object targetDestinationResolver = ReflectionTestUtils.getField(destinationResolver, "targetDestinationResolver"); assertEquals(ConfigurationWithCustomizedMessageHandler.CUSTOM_RESOURCE_ID_RESOLVER, ReflectionTestUtils.getField(targetDestinationResolver, "resourceIdResolver")); } @Test public void configuration_withCustomConfigurationFactory_shouldBeUsedToCreateTheContainer() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationWithCustomContainerFactory.class); SimpleMessageListenerContainer container = applicationContext.getBean(SimpleMessageListenerContainer.class); // Assert assertEquals(ConfigurationWithCustomContainerFactory.AMAZON_SQS, ReflectionTestUtils.getField(container, "amazonSqs")); assertEquals(ConfigurationWithCustomContainerFactory.AUTO_STARTUP, container.isAutoStartup()); assertEquals(ConfigurationWithCustomContainerFactory.MAX_NUMBER_OF_MESSAGES, ReflectionTestUtils.getField(container, "maxNumberOfMessages")); assertEquals(ConfigurationWithCustomContainerFactory.MESSAGE_HANDLER, ReflectionTestUtils.getField(container, "messageHandler")); assertEquals(ConfigurationWithCustomContainerFactory.RESOURCE_ID_RESOLVER, ReflectionTestUtils.getField(container, "resourceIdResolver")); assertEquals(ConfigurationWithCustomContainerFactory.TASK_EXECUTOR, ReflectionTestUtils.getField(container, "taskExecutor")); assertEquals(ConfigurationWithCustomContainerFactory.VISIBILITY_TIMEOUT, ReflectionTestUtils.getField(container, "visibilityTimeout")); assertEquals(ConfigurationWithCustomContainerFactory.WAIT_TIME_OUT, ReflectionTestUtils.getField(container, "waitTimeOut")); assertTrue(ConfigurationWithCustomContainerFactory.DESTINATION_RESOLVER == ReflectionTestUtils.getField(container, "destinationResolver")); assertEquals(ConfigurationWithCustomContainerFactory.BACK_OFF_TIME, container.getBackOffTime()); } @Test public void configuration_withCustomSendToMessageTemplate_shouldUseTheConfiguredTemplate() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationWithCustomSendToMessageTemplate.class); QueueMessageHandler queueMessageHandler = applicationContext.getBean(QueueMessageHandler.class); // Assert assertEquals(1, queueMessageHandler.getReturnValueHandlers().size()); assertTrue(ConfigurationWithCustomSendToMessageTemplate.SEND_TO_MESSAGE_TEMPLATE == ReflectionTestUtils.getField(queueMessageHandler.getReturnValueHandlers().get(0), "messageTemplate")); } @Test public void queueMessageHandlerBeanMustBeSetOnContainer() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MinimalConfiguration.class); SimpleMessageListenerContainer simpleMessageListenerContainer = applicationContext.getBean(SimpleMessageListenerContainer.class); QueueMessageHandler queueMessageHandler = applicationContext.getBean(QueueMessageHandler.class); // Assert assertEquals(queueMessageHandler, ReflectionTestUtils.getField(simpleMessageListenerContainer, "messageHandler")); } @Test public void configuration_withoutAwsCredentials_shouldCreateAClientWithDefaultCredentialsProvider() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationWithMissingAwsCredentials.class); // Assert AmazonSQSBufferedAsyncClient bufferedAmazonSqsClient = applicationContext.getBean(AmazonSQSBufferedAsyncClient.class); AmazonSQSAsyncClient amazonSqsClient = (AmazonSQSAsyncClient) ReflectionTestUtils.getField(bufferedAmazonSqsClient, "realSQS"); assertTrue(DefaultAWSCredentialsProviderChain.class.isInstance(ReflectionTestUtils.getField(amazonSqsClient, "awsCredentialsProvider"))); } @Test public void configuration_withRegionProvider_shouldUseItForClient() throws Exception { // Arrange & Act AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationWithRegionProvider.class); AmazonSQSAsync bufferedAmazonSqsClient = applicationContext.getBean(AmazonSQSAsync.class); AmazonSQSAsyncClient amazonSqs = (AmazonSQSAsyncClient) ReflectionTestUtils.getField(bufferedAmazonSqsClient, "realSQS"); // Assert assertEquals("https://" + Region.getRegion(Regions.EU_WEST_1).getServiceEndpoint("sqs"), ReflectionTestUtils.getField(amazonSqs, "endpoint").toString()); } @EnableSqs @Configuration public static class MinimalConfiguration { @Bean public AWSCredentialsProvider awsCredentials() { return mock(AWSCredentialsProvider.class); } } @EnableSqs @Configuration public static class ConfigurationWithCustomAmazonClient { public static final AmazonSQSAsync CUSTOM_SQS_CLIENT = mock(AmazonSQSAsync.class, withSettings().stubOnly()); @Bean public AWSCredentialsProvider awsCredentials() { return mock(AWSCredentialsProvider.class); } @Bean public AmazonSQSAsync amazonSQS() { return CUSTOM_SQS_CLIENT; } } @EnableSqs @Configuration public static class ConfigurationWithCustomizedMessageHandler extends MinimalConfiguration { public static final HandlerMethodReturnValueHandler CUSTOM_RETURN_VALUE_HANDLER = mock(HandlerMethodReturnValueHandler.class); public static final HandlerMethodArgumentResolver CUSTOM_ARGUMENT_RESOLVER = mock(HandlerMethodArgumentResolver.class); public static final AmazonSQSAsync CUSTOM_AMAZON_SQS = mock(AmazonSQSAsync.class, withSettings().stubOnly()); public static final ResourceIdResolver CUSTOM_RESOURCE_ID_RESOLVER = mock(ResourceIdResolver.class); @Bean public QueueMessageHandlerFactory queueMessageHandlerFactory() { QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory(); factory.setArgumentResolvers(Collections.singletonList(CUSTOM_ARGUMENT_RESOLVER)); factory.setReturnValueHandlers(Collections.singletonList(CUSTOM_RETURN_VALUE_HANDLER)); factory.setAmazonSqs(CUSTOM_AMAZON_SQS); factory.setResourceIdResolver(CUSTOM_RESOURCE_ID_RESOLVER); return factory; } } @EnableSqs @Configuration public static class ConfigurationWithCustomContainerFactory { public static final AmazonSQSAsync AMAZON_SQS = mock(AmazonSQSAsync.class, withSettings().stubOnly()); public static final boolean AUTO_STARTUP = true; public static final int MAX_NUMBER_OF_MESSAGES = 1456; public static final QueueMessageHandler MESSAGE_HANDLER; public static final ResourceIdResolver RESOURCE_ID_RESOLVER = mock(ResourceIdResolver.class); public static final SimpleAsyncTaskExecutor TASK_EXECUTOR = new SimpleAsyncTaskExecutor(); public static final int VISIBILITY_TIMEOUT = 1789; public static final int WAIT_TIME_OUT = 12; public static final DestinationResolver<String> DESTINATION_RESOLVER = new DynamicQueueUrlDestinationResolver(mock(AmazonSQSAsync.class, withSettings().stubOnly())); public static final long BACK_OFF_TIME = 5000; static { QueueMessageHandler queueMessageHandler = new QueueMessageHandler(); queueMessageHandler.setApplicationContext(new StaticApplicationContext()); MESSAGE_HANDLER = queueMessageHandler; } @Bean public SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory() { SimpleMessageListenerContainerFactory factory = new SimpleMessageListenerContainerFactory(); factory.setAmazonSqs(amazonSQS()); factory.setAutoStartup(AUTO_STARTUP); factory.setMaxNumberOfMessages(MAX_NUMBER_OF_MESSAGES); factory.setQueueMessageHandler(MESSAGE_HANDLER); factory.setResourceIdResolver(RESOURCE_ID_RESOLVER); factory.setTaskExecutor(TASK_EXECUTOR); factory.setVisibilityTimeout(VISIBILITY_TIMEOUT); factory.setWaitTimeOut(WAIT_TIME_OUT); factory.setDestinationResolver(DESTINATION_RESOLVER); factory.setBackOffTime(BACK_OFF_TIME); return factory; } @Bean public AmazonSQSAsync amazonSQS() { return AMAZON_SQS; } } @EnableSqs @Configuration public static class ConfigurationWithCustomSendToMessageTemplate { public static final DestinationResolvingMessageSendingOperations<?> SEND_TO_MESSAGE_TEMPLATE = mock(DestinationResolvingMessageSendingOperations.class); @Bean public QueueMessageHandlerFactory queueMessageHandlerFactory() { QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory(); factory.setSendToMessagingTemplate(SEND_TO_MESSAGE_TEMPLATE); return factory; } } @EnableSqs @Configuration public static class ConfigurationWithMissingAwsCredentials { } @EnableSqs @EnableContextRegion(region = "eu-west-1") @Configuration public static class ConfigurationWithRegionProvider { } }