/*
* Copyright 2002-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.jms.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import org.hamcrest.core.Is;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.annotation.AliasFor;
import org.springframework.jms.config.JmsListenerContainerTestFactory;
import org.springframework.jms.config.JmsListenerEndpointRegistrar;
import org.springframework.jms.config.JmsListenerEndpointRegistry;
import org.springframework.jms.config.MessageListenerTestContainer;
import org.springframework.jms.config.MethodJmsListenerEndpoint;
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
import org.springframework.jms.listener.adapter.ListenerExecutionFailedException;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
import org.springframework.stereotype.Component;
import static org.junit.Assert.*;
/**
* @author Stephane Nicoll
* @author Sam Brannen
*/
public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Override
@Test
public void sampleConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsSampleConfig.class, SampleBean.class);
testSampleConfiguration(context);
}
@Override
@Test
public void fullConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsFullConfig.class, FullBean.class);
testFullConfiguration(context);
}
@Override
public void fullConfigurableConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsFullConfigurableConfig.class, FullConfigurableBean.class);
testFullConfiguration(context);
}
@Override
@Test
public void customConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsCustomConfig.class, CustomBean.class);
testCustomConfiguration(context);
}
@Override
@Test
public void explicitContainerFactory() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsCustomContainerFactoryConfig.class, DefaultBean.class);
testExplicitContainerFactoryConfiguration(context);
}
@Override
@Test
public void defaultContainerFactory() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, DefaultBean.class);
testDefaultContainerFactoryConfiguration(context);
}
@Test
public void containerAreStartedByDefault() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, DefaultBean.class);
JmsListenerContainerTestFactory factory =
context.getBean(JmsListenerContainerTestFactory.class);
MessageListenerTestContainer container = factory.getListenerContainers().get(0);
assertTrue(container.isAutoStartup());
assertTrue(container.isStarted());
}
@Test
public void containerCanBeStarterViaTheRegistry() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsAutoStartupFalseConfig.class, DefaultBean.class);
JmsListenerContainerTestFactory factory =
context.getBean(JmsListenerContainerTestFactory.class);
MessageListenerTestContainer container = factory.getListenerContainers().get(0);
assertFalse(container.isAutoStartup());
assertFalse(container.isStarted());
JmsListenerEndpointRegistry registry = context.getBean(JmsListenerEndpointRegistry.class);
registry.start();
assertTrue(container.isStarted());
}
@Override
@Test
public void jmsHandlerMethodFactoryConfiguration() throws JMSException {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsHandlerMethodFactoryConfig.class, ValidationBean.class);
thrown.expect(ListenerExecutionFailedException.class);
thrown.expectCause(Is.<MethodArgumentNotValidException>isA(MethodArgumentNotValidException.class));
testJmsHandlerMethodFactoryConfiguration(context);
}
@Override
@Test
public void jmsListenerIsRepeatable() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, JmsListenerRepeatableBean.class);
testJmsListenerRepeatable(context);
}
@Override
@Test
public void jmsListeners() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, JmsListenersBean.class);
testJmsListenerRepeatable(context);
}
@Test
public void composedJmsListeners() {
try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, ComposedJmsListenersBean.class)) {
JmsListenerContainerTestFactory simpleFactory = context.getBean("jmsListenerContainerFactory",
JmsListenerContainerTestFactory.class);
assertEquals(2, simpleFactory.getListenerContainers().size());
MethodJmsListenerEndpoint first = (MethodJmsListenerEndpoint) simpleFactory.getListenerContainer(
"first").getEndpoint();
assertEquals("first", first.getId());
assertEquals("orderQueue", first.getDestination());
assertNull(first.getConcurrency());
MethodJmsListenerEndpoint second = (MethodJmsListenerEndpoint) simpleFactory.getListenerContainer(
"second").getEndpoint();
assertEquals("second", second.getId());
assertEquals("billingQueue", second.getDestination());
assertEquals("2-10", second.getConcurrency());
}
}
@Test
@SuppressWarnings("resource")
public void unknownFactory() {
thrown.expect(BeanCreationException.class);
thrown.expectMessage("customFactory"); // not found
new AnnotationConfigApplicationContext(EnableJmsSampleConfig.class, CustomBean.class);
}
@Test
public void lazyComponent() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, LazyBean.class);
JmsListenerContainerTestFactory defaultFactory =
context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
assertEquals(0, defaultFactory.getListenerContainers().size());
context.getBean(LazyBean.class); // trigger lazy resolution
assertEquals(1, defaultFactory.getListenerContainers().size());
MessageListenerTestContainer container = defaultFactory.getListenerContainers().get(0);
assertTrue("Should have been started " + container, container.isStarted());
context.close(); // close and stop the listeners
assertTrue("Should have been stopped " + container, container.isStopped());
}
@EnableJms
@Configuration
static class EnableJmsSampleConfig {
@Bean
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
}
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
}
@EnableJms
@Configuration
static class EnableJmsFullConfig {
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
}
@EnableJms
@Configuration
@PropertySource("classpath:/org/springframework/jms/annotation/jms-listener.properties")
static class EnableJmsFullConfigurableConfig {
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
@Configuration
@EnableJms
static class EnableJmsCustomConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setEndpointRegistry(customRegistry());
// Also register a custom endpoint
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue");
endpoint.setMessageListener(simpleMessageListener());
registrar.registerEndpoint(endpoint);
}
@Bean
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
}
@Bean
public JmsListenerEndpointRegistry customRegistry() {
return new JmsListenerEndpointRegistry();
}
@Bean
public JmsListenerContainerTestFactory customFactory() {
return new JmsListenerContainerTestFactory();
}
@Bean
public MessageListener simpleMessageListener() {
return new MessageListenerAdapter();
}
}
@Configuration
@EnableJms
static class EnableJmsCustomContainerFactoryConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setContainerFactory(simpleFactory());
}
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@EnableJms
static class EnableJmsDefaultContainerFactoryConfig {
@Bean
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@EnableJms
static class EnableJmsHandlerMethodFactoryConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(customMessageHandlerMethodFactory());
}
@Bean
public MessageHandlerMethodFactory customMessageHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
factory.setValidator(new TestValidator());
return factory;
}
@Bean
public JmsListenerContainerTestFactory defaultFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@EnableJms
static class EnableJmsAutoStartupFalseConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setContainerFactory(simpleFactory());
}
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
JmsListenerContainerTestFactory factory = new JmsListenerContainerTestFactory();
factory.setAutoStartup(false);
return factory;
}
}
@Component
@Lazy
static class LazyBean {
@JmsListener(destination = "myQueue")
public void handle(String msg) {
}
}
@JmsListener(destination = "orderQueue")
@Retention(RetentionPolicy.RUNTIME)
private @interface OrderQueueListener {
@AliasFor(annotation = JmsListener.class)
String id() default "";
@AliasFor(annotation = JmsListener.class)
String concurrency() default "";
}
@JmsListener(destination = "billingQueue")
@Retention(RetentionPolicy.RUNTIME)
private @interface BillingQueueListener {
@AliasFor(annotation = JmsListener.class)
String id() default "";
@AliasFor(annotation = JmsListener.class)
String concurrency() default "";
}
@Component
static class ComposedJmsListenersBean {
@OrderQueueListener(id = "first")
@BillingQueueListener(id = "second", concurrency = "2-10")
public void repeatableHandle(String msg) {
}
}
}