/* * Copyright 2012-2016 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.boot.autoconfigure.jms; import javax.jms.ConnectionFactory; import javax.jms.Session; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.pool.PooledConnectionFactory; import org.junit.After; import org.junit.Test; import org.springframework.beans.BeansException; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration; import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jms.annotation.EnableJms; import org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.config.JmsListenerConfigUtils; import org.springframework.jms.config.JmsListenerContainerFactory; import org.springframework.jms.config.JmsListenerEndpoint; import org.springframework.jms.config.SimpleJmsListenerContainerFactory; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.listener.DefaultMessageListenerContainer; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.destination.DestinationResolver; import org.springframework.transaction.jta.JtaTransactionManager; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; /** * Tests for {@link JmsAutoConfiguration}. * * @author Greg Turnquist * @author Stephane Nicoll * @author Aurélien Leboulanger */ public class JmsAutoConfigurationTests { private static final String ACTIVEMQ_EMBEDDED_URL = "vm://localhost?broker.persistent=false"; private static final String ACTIVEMQ_NETWORK_URL = "tcp://localhost:61616"; private AnnotationConfigApplicationContext context; @After public void close() { if (this.context != null) { this.context.close(); } } @Test public void testDefaultJmsConfiguration() { load(TestConfiguration.class); ActiveMQConnectionFactory connectionFactory = this.context .getBean(ActiveMQConnectionFactory.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); JmsMessagingTemplate messagingTemplate = this.context .getBean(JmsMessagingTemplate.class); assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) .getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL); assertThat(this.context.containsBean("jmsListenerContainerFactory")).isTrue(); } @Test public void testConnectionFactoryBackOff() { load(TestConfiguration2.class); assertThat(this.context.getBean(ActiveMQConnectionFactory.class).getBrokerURL()) .isEqualTo("foobar"); } @Test public void testJmsTemplateBackOff() { load(TestConfiguration3.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.getPriority()).isEqualTo(999); } @Test public void testJmsMessagingTemplateBackOff() { load(TestConfiguration5.class); JmsMessagingTemplate messagingTemplate = this.context .getBean(JmsMessagingTemplate.class); assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar"); } @Test public void testJmsTemplateBackOffEverything() { this.context = createContext(TestConfiguration2.class, TestConfiguration3.class, TestConfiguration5.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.getPriority()).isEqualTo(999); assertThat(this.context.getBean(ActiveMQConnectionFactory.class).getBrokerURL()) .isEqualTo("foobar"); JmsMessagingTemplate messagingTemplate = this.context .getBean(JmsMessagingTemplate.class); assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar"); assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); } @Test public void testEnableJmsCreateDefaultContainerFactory() { load(EnableJmsConfiguration.class); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "jmsListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory.getClass()) .isEqualTo(DefaultJmsListenerContainerFactory.class); } @Test public void testJmsListenerContainerFactoryBackOff() { this.context = createContext(TestConfiguration6.class, EnableJmsConfiguration.class); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "jmsListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory.getClass()) .isEqualTo(SimpleJmsListenerContainerFactory.class); } @Test public void testJmsListenerContainerFactoryWithCustomSettings() { load(EnableJmsConfiguration.class, "spring.jms.listener.autoStartup=false", "spring.jms.listener.acknowledgeMode=client", "spring.jms.listener.concurrency=2", "spring.jms.listener.maxConcurrency=10"); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "jmsListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory.getClass()) .isEqualTo(DefaultJmsListenerContainerFactory.class); DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) .createListenerContainer(mock(JmsListenerEndpoint.class)); assertThat(listenerContainer.isAutoStartup()).isFalse(); assertThat(listenerContainer.getSessionAcknowledgeMode()) .isEqualTo(Session.CLIENT_ACKNOWLEDGE); assertThat(listenerContainer.getConcurrentConsumers()).isEqualTo(2); assertThat(listenerContainer.getMaxConcurrentConsumers()).isEqualTo(10); } @Test public void testDefaultContainerFactoryWithJtaTransactionManager() { this.context = createContext(TestConfiguration7.class, EnableJmsConfiguration.class); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "jmsListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory.getClass()) .isEqualTo(DefaultJmsListenerContainerFactory.class); DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) .createListenerContainer(mock(JmsListenerEndpoint.class)); assertThat(listenerContainer.isSessionTransacted()).isFalse(); assertThat(new DirectFieldAccessor(listenerContainer) .getPropertyValue("transactionManager")) .isSameAs(this.context.getBean(JtaTransactionManager.class)); } @Test public void testDefaultContainerFactoryNonJtaTransactionManager() { this.context = createContext(TestConfiguration8.class, EnableJmsConfiguration.class); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "jmsListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory.getClass()) .isEqualTo(DefaultJmsListenerContainerFactory.class); DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) .createListenerContainer(mock(JmsListenerEndpoint.class)); assertThat(listenerContainer.isSessionTransacted()).isTrue(); assertThat(new DirectFieldAccessor(listenerContainer) .getPropertyValue("transactionManager")).isNull(); } @Test public void testDefaultContainerFactoryNoTransactionManager() { this.context = createContext(EnableJmsConfiguration.class); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "jmsListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory.getClass()) .isEqualTo(DefaultJmsListenerContainerFactory.class); DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) .createListenerContainer(mock(JmsListenerEndpoint.class)); assertThat(listenerContainer.isSessionTransacted()).isTrue(); assertThat(new DirectFieldAccessor(listenerContainer) .getPropertyValue("transactionManager")).isNull(); } @Test public void testDefaultContainerFactoryWithMessageConverters() { this.context = createContext(MessageConvertersConfiguration.class, EnableJmsConfiguration.class); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "jmsListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory.getClass()) .isEqualTo(DefaultJmsListenerContainerFactory.class); DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) .createListenerContainer(mock(JmsListenerEndpoint.class)); assertThat(listenerContainer.getMessageConverter()) .isSameAs(this.context.getBean("myMessageConverter")); } @Test public void testCustomContainerFactoryWithConfigurer() { this.context = doLoad( new Class<?>[] { TestConfiguration9.class, EnableJmsConfiguration.class }, "spring.jms.listener.autoStartup=false"); assertThat(this.context.containsBean("jmsListenerContainerFactory")).isTrue(); JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean( "customListenerContainerFactory", JmsListenerContainerFactory.class); assertThat(jmsListenerContainerFactory) .isInstanceOf(DefaultJmsListenerContainerFactory.class); DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) .createListenerContainer(mock(JmsListenerEndpoint.class)); assertThat(listenerContainer.getCacheLevel()) .isEqualTo(DefaultMessageListenerContainer.CACHE_CONSUMER); assertThat(listenerContainer.isAutoStartup()).isFalse(); } @Test public void testJmsTemplateWithMessageConverter() { load(MessageConvertersConfiguration.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.getMessageConverter()) .isSameAs(this.context.getBean("myMessageConverter")); } @Test public void testJmsTemplateWithDestinationResolver() { load(DestinationResolversConfiguration.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.getDestinationResolver()) .isSameAs(this.context.getBean("myDestinationResolver")); } @Test public void testJmsTemplateFullCustomization() { load(MessageConvertersConfiguration.class, "spring.jms.template.default-destination=testQueue", "spring.jms.template.delivery-delay=500", "spring.jms.template.delivery-mode=non-persistent", "spring.jms.template.priority=6", "spring.jms.template.time-to-live=6000", "spring.jms.template.receive-timeout=2000"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.getMessageConverter()) .isSameAs(this.context.getBean("myMessageConverter")); assertThat(jmsTemplate.isPubSubDomain()).isFalse(); assertThat(jmsTemplate.getDefaultDestinationName()).isEqualTo("testQueue"); assertThat(jmsTemplate.getDeliveryDelay()).isEqualTo(500); assertThat(jmsTemplate.getDeliveryMode()).isEqualTo(1); assertThat(jmsTemplate.getPriority()).isEqualTo(6); assertThat(jmsTemplate.getTimeToLive()).isEqualTo(6000); assertThat(jmsTemplate.isExplicitQosEnabled()).isTrue(); assertThat(jmsTemplate.getReceiveTimeout()).isEqualTo(2000); } @Test public void testPubSubDisabledByDefault() { load(TestConfiguration.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.isPubSubDomain()).isFalse(); } @Test public void testJmsTemplatePostProcessedSoThatPubSubIsTrue() { load(TestConfiguration4.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.isPubSubDomain()).isTrue(); } @Test public void testPubSubDomainActive() { load(TestConfiguration.class, "spring.jms.pubSubDomain:true"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); DefaultMessageListenerContainer defaultMessageListenerContainer = this.context .getBean(DefaultJmsListenerContainerFactory.class) .createListenerContainer(mock(JmsListenerEndpoint.class)); assertThat(jmsTemplate.isPubSubDomain()).isTrue(); assertThat(defaultMessageListenerContainer.isPubSubDomain()).isTrue(); } @Test public void testPubSubDomainOverride() { load(TestConfiguration.class, "spring.jms.pubSubDomain:false"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); ActiveMQConnectionFactory connectionFactory = this.context .getBean(ActiveMQConnectionFactory.class); assertThat(jmsTemplate).isNotNull(); assertThat(jmsTemplate.isPubSubDomain()).isFalse(); assertThat(connectionFactory).isNotNull(); assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); } @Test public void testActiveMQOverriddenStandalone() { load(TestConfiguration.class, "spring.activemq.inMemory:false"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); ActiveMQConnectionFactory connectionFactory = this.context .getBean(ActiveMQConnectionFactory.class); assertThat(jmsTemplate).isNotNull(); assertThat(connectionFactory).isNotNull(); assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) .getBrokerURL()).isEqualTo(ACTIVEMQ_NETWORK_URL); } @Test public void testActiveMQOverriddenRemoteHost() { load(TestConfiguration.class, "spring.activemq.brokerUrl:tcp://remote-host:10000"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); ActiveMQConnectionFactory connectionFactory = this.context .getBean(ActiveMQConnectionFactory.class); assertThat(jmsTemplate).isNotNull(); assertThat(connectionFactory).isNotNull(); assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) .getBrokerURL()).isEqualTo("tcp://remote-host:10000"); } @Test public void testActiveMQOverriddenPool() { load(TestConfiguration.class, "spring.activemq.pool.enabled:true"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); PooledConnectionFactory pool = this.context .getBean(PooledConnectionFactory.class); assertThat(jmsTemplate).isNotNull(); assertThat(pool).isNotNull(); assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool .getConnectionFactory(); assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL); } @Test public void testActiveMQOverriddenPoolAndStandalone() { load(TestConfiguration.class, "spring.activemq.pool.enabled:true", "spring.activemq.inMemory:false"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); PooledConnectionFactory pool = this.context .getBean(PooledConnectionFactory.class); assertThat(jmsTemplate).isNotNull(); assertThat(pool).isNotNull(); assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool .getConnectionFactory(); assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_NETWORK_URL); } @Test public void testActiveMQOverriddenPoolAndRemoteServer() { load(TestConfiguration.class, "spring.activemq.pool.enabled:true", "spring.activemq.brokerUrl:tcp://remote-host:10000"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); PooledConnectionFactory pool = this.context .getBean(PooledConnectionFactory.class); assertThat(jmsTemplate).isNotNull(); assertThat(pool).isNotNull(); assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool .getConnectionFactory(); assertThat(factory.getBrokerURL()).isEqualTo("tcp://remote-host:10000"); } @Test public void enableJmsAutomatically() throws Exception { load(NoEnableJmsConfiguration.class); AnnotationConfigApplicationContext ctx = this.context; ctx.getBean(JmsListenerConfigUtils.JMS_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME); ctx.getBean(JmsListenerConfigUtils.JMS_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME); } private AnnotationConfigApplicationContext createContext( Class<?>... additionalClasses) { return doLoad(additionalClasses); } private void load(Class<?> config, String... environment) { this.context = doLoad(new Class<?>[] { config }, environment); } private AnnotationConfigApplicationContext doLoad(Class<?>[] configs, String... environment) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); applicationContext.register(configs); applicationContext.register(ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(applicationContext, environment); applicationContext.refresh(); return applicationContext; } @Configuration protected static class TestConfiguration { } @Configuration protected static class TestConfiguration2 { @Bean ConnectionFactory connectionFactory() { return new ActiveMQConnectionFactory() { { setBrokerURL("foobar"); } }; } } @Configuration protected static class TestConfiguration3 { @Bean JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) { JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); jmsTemplate.setPriority(999); return jmsTemplate; } } @Configuration protected static class TestConfiguration4 implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean.getClass().isAssignableFrom(JmsTemplate.class)) { JmsTemplate jmsTemplate = (JmsTemplate) bean; jmsTemplate.setPubSubDomain(true); } return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } } @Configuration protected static class TestConfiguration5 { @Bean JmsMessagingTemplate jmsMessagingTemplate(JmsTemplate jmsTemplate) { JmsMessagingTemplate messagingTemplate = new JmsMessagingTemplate( jmsTemplate); messagingTemplate.setDefaultDestinationName("fooBar"); return messagingTemplate; } } @Configuration protected static class TestConfiguration6 { @Bean JmsListenerContainerFactory<?> jmsListenerContainerFactory( ConnectionFactory connectionFactory) { SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); return factory; } } @Configuration protected static class TestConfiguration7 { @Bean JtaTransactionManager transactionManager() { return mock(JtaTransactionManager.class); } } @Configuration protected static class TestConfiguration8 { @Bean DataSourceTransactionManager transactionManager() { return mock(DataSourceTransactionManager.class); } } @Configuration protected static class MessageConvertersConfiguration { @Bean @Primary public MessageConverter myMessageConverter() { return mock(MessageConverter.class); } @Bean public MessageConverter anotherMessageConverter() { return mock(MessageConverter.class); } } @Configuration protected static class DestinationResolversConfiguration { @Bean @Primary public DestinationResolver myDestinationResolver() { return mock(DestinationResolver.class); } @Bean public DestinationResolver anotherDestinationResolver() { return mock(DestinationResolver.class); } } @Configuration protected static class TestConfiguration9 { @Bean JmsListenerContainerFactory<?> customListenerContainerFactory( DefaultJmsListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); configurer.configure(factory, connectionFactory); factory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER); return factory; } } @Configuration @EnableJms protected static class EnableJmsConfiguration { } @Configuration protected static class NoEnableJmsConfiguration { } }