Revision of JMS annotated endpoint support, plus support for JMS 2.0's shared subscriptions

Issue: SPR-9882
Issue: SPR-11969
This commit is contained in:
Juergen Hoeller
2014-07-18 17:21:21 +02:00
parent 3e5946db37
commit a9100c427c
39 changed files with 873 additions and 786 deletions

View File

@@ -76,8 +76,8 @@ public abstract class AbstractJmsAnnotationDrivenTests {
context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory simpleFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
assertEquals(1, simpleFactory.getContainers().size());
assertEquals(1, defaultFactory.getListenerContainers().size());
assertEquals(1, simpleFactory.getListenerContainers().size());
}
@Component
@@ -100,9 +100,9 @@ public abstract class AbstractJmsAnnotationDrivenTests {
public void testFullConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory simpleFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, simpleFactory.getContainers().size());
assertEquals(1, simpleFactory.getListenerContainers().size());
MethodJmsListenerEndpoint endpoint = (MethodJmsListenerEndpoint)
simpleFactory.getContainers().get(0).getEndpoint();
simpleFactory.getListenerContainers().get(0).getEndpoint();
assertEquals("listener1", endpoint.getId());
assertEquals("queueIn", endpoint.getDestination());
assertEquals("mySelector", endpoint.getSelector());
@@ -129,9 +129,9 @@ public abstract class AbstractJmsAnnotationDrivenTests {
context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory customFactory =
context.getBean("customFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
assertEquals(1, customFactory.getContainers().size());
JmsListenerEndpoint endpoint = defaultFactory.getContainers().get(0).getEndpoint();
assertEquals(1, defaultFactory.getListenerContainers().size());
assertEquals(1, customFactory.getListenerContainers().size());
JmsListenerEndpoint endpoint = defaultFactory.getListenerContainers().get(0).getEndpoint();
assertEquals("Wrong endpoint type", SimpleJmsListenerEndpoint.class, endpoint.getClass());
assertEquals("Wrong listener set in custom endpoint", context.getBean("simpleMessageListener"),
((SimpleJmsListenerEndpoint) endpoint).getMessageListener());
@@ -139,11 +139,11 @@ public abstract class AbstractJmsAnnotationDrivenTests {
JmsListenerEndpointRegistry customRegistry =
context.getBean("customRegistry", JmsListenerEndpointRegistry.class);
assertEquals("Wrong number of containers in the registry", 2,
customRegistry.getContainers().size());
customRegistry.getListenerContainers().size());
assertNotNull("Container with custom id on the annotation should be found",
customRegistry.getContainer("listenerId"));
customRegistry.getListenerContainer("listenerId"));
assertNotNull("Container created with custom id should be found",
customRegistry.getContainer("myCustomEndpointId"));
customRegistry.getListenerContainer("myCustomEndpointId"));
}
@Component
@@ -162,7 +162,7 @@ public abstract class AbstractJmsAnnotationDrivenTests {
public void testExplicitContainerFactoryConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
assertEquals(1, defaultFactory.getListenerContainers().size());
}
/**
@@ -172,7 +172,7 @@ public abstract class AbstractJmsAnnotationDrivenTests {
public void testDefaultContainerFactoryConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
assertEquals(1, defaultFactory.getListenerContainers().size());
}
static class DefaultBean {
@@ -191,12 +191,12 @@ public abstract class AbstractJmsAnnotationDrivenTests {
public void testJmsHandlerMethodFactoryConfiguration(ApplicationContext context) throws JMSException {
JmsListenerContainerTestFactory simpleFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, simpleFactory.getContainers().size());
assertEquals(1, simpleFactory.getListenerContainers().size());
MethodJmsListenerEndpoint endpoint = (MethodJmsListenerEndpoint)
simpleFactory.getContainers().get(0).getEndpoint();
simpleFactory.getListenerContainers().get(0).getEndpoint();
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
endpoint.setupMessageContainer(container);
endpoint.setupListenerContainer(container);
MessagingMessageListenerAdapter listener = (MessagingMessageListenerAdapter) container.getMessageListener();
listener.onMessage(new StubTextMessage("failValidation"), mock(Session.class));
}

View File

@@ -16,8 +16,6 @@
package org.springframework.jms.annotation;
import static org.junit.Assert.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -38,47 +36,51 @@ import org.springframework.jms.config.MethodJmsListenerEndpoint;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.stereotype.Component;
import static org.junit.Assert.*;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerAnnotationBeanPostProcessorTests {
@Test
public void simpleMessageListener() {
final ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(Config.class,
SimpleMessageListenerTestBean.class);
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
Config.class, SimpleMessageListenerTestBean.class);
JmsListenerContainerTestFactory factory = context.getBean(JmsListenerContainerTestFactory.class);
assertEquals("one container should have been registered", 1, factory.getContainers().size());
MessageListenerTestContainer container = factory.getContainers().get(0);
assertEquals("One container should have been registered", 1, factory.getListenerContainers().size());
MessageListenerTestContainer container = factory.getListenerContainers().get(0);
JmsListenerEndpoint endpoint = container.getEndpoint();
assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass());
MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint;
assertNotNull(methodEndpoint.getBean());
assertNotNull(methodEndpoint.getMethod());
assertTrue("Should have been started " + container, container.isStarted());
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
methodEndpoint.setupMessageContainer(listenerContainer);
methodEndpoint.setupListenerContainer(listenerContainer);
assertNotNull(listenerContainer.getMessageListener());
context.start();
assertTrue("Should have been started " + container, container.isStarted());
context.close(); // Close and stop the listeners
assertTrue("Should have been stopped " + container, container.isStopped());
}
@Test
public void metaAnnotationIsDiscovered() {
final ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(Config.class,
MetaAnnotationTestBean.class);
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
Config.class, MetaAnnotationTestBean.class);
JmsListenerContainerTestFactory factory = context.getBean(JmsListenerContainerTestFactory.class);
assertEquals("one container should have been registered", 1, factory.getContainers().size());
JmsListenerEndpoint endpoint = factory.getContainers().get(0).getEndpoint();
assertEquals("one container should have been registered", 1, factory.getListenerContainers().size());
JmsListenerEndpoint endpoint = factory.getListenerContainers().get(0).getEndpoint();
assertEquals("metaTestQueue", ((AbstractJmsListenerEndpoint) endpoint).getDestination());
}
@Component
static class SimpleMessageListenerTestBean {
@@ -88,6 +90,7 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
}
@Component
static class MetaAnnotationTestBean {
@@ -101,9 +104,9 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
static @interface FooListener {
}
@Configuration
static class Config {
@@ -124,6 +127,6 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
public JmsListenerContainerTestFactory testFactory() {
return new JmsListenerContainerTestFactory();
}
}
}

View File

@@ -83,7 +83,7 @@ public class JmsListenerContainerFactoryIntegrationTests {
@SuppressWarnings("unchecked")
private void invokeListener(JmsListenerEndpoint endpoint, Message message) throws JMSException {
DefaultMessageListenerContainer messageListenerContainer =
containerFactory.createMessageListenerContainer(endpoint);
containerFactory.createListenerContainer(endpoint);
Object listener = messageListenerContainer.getMessageListener();
if (listener instanceof SessionAwareMessageListener) {
((SessionAwareMessageListener<Message>) listener).onMessage(message, mock(Session.class));

View File

@@ -45,7 +45,6 @@ import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerContainerFactoryTests {
@@ -61,6 +60,7 @@ public class JmsListenerContainerFactoryTests {
private final TransactionManager transactionManager = mock(TransactionManager.class);
@Test
public void createSimpleContainer() {
SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
@@ -71,14 +71,13 @@ public class JmsListenerContainerFactoryTests {
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
SimpleMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
SimpleMessageListenerContainer container = factory.createListenerContainer(endpoint);
assertDefaultJmsConfig(container);
assertEquals(messageListener, container.getMessageListener());
assertEquals("myQueue", container.getDestinationName());
}
@Test
public void createJmsContainerFullConfig() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
@@ -91,7 +90,7 @@ public class JmsListenerContainerFactoryTests {
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
DefaultMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
DefaultMessageListenerContainer container = factory.createListenerContainer(endpoint);
assertDefaultJmsConfig(container);
assertEquals(DefaultMessageListenerContainer.CACHE_CONSUMER, container.getCacheLevel());
@@ -107,13 +106,13 @@ public class JmsListenerContainerFactoryTests {
public void createJcaContainerFullConfig() {
DefaultJcaListenerContainerFactory factory = new DefaultJcaListenerContainerFactory();
setDefaultJcaConfig(factory);
factory.getActivationSpecConfig().setConcurrency("10");
factory.setConcurrency("10");
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
JmsMessageEndpointManager container = factory.createMessageListenerContainer(endpoint);
JmsMessageEndpointManager container = factory.createListenerContainer(endpoint);
assertDefaultJcaConfig(container);
assertEquals(10, container.getActivationSpecConfig().getMaxConcurrency());
@@ -130,7 +129,7 @@ public class JmsListenerContainerFactoryTests {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setMessageListener(new MessageListenerAdapter());
thrown.expect(IllegalStateException.class);
factory.createMessageListenerContainer(endpoint);
factory.createListenerContainer(endpoint);
}
@Test
@@ -144,7 +143,7 @@ public class JmsListenerContainerFactoryTests {
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
DefaultMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
DefaultMessageListenerContainer container = factory.createListenerContainer(endpoint);
assertSame(backOff, new DirectFieldAccessor(container).getPropertyValue("backOff"));
}
@@ -174,13 +173,11 @@ public class JmsListenerContainerFactoryTests {
private void setDefaultJcaConfig(DefaultJcaListenerContainerFactory factory) {
factory.setDestinationResolver(destinationResolver);
factory.setTransactionManager(transactionManager);
JmsActivationSpecConfig config = new JmsActivationSpecConfig();
config.setMessageConverter(messageConverter);
config.setAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE);
config.setPubSubDomain(true);
config.setSubscriptionDurable(true);
config.setClientId("client-1234");
factory.setActivationSpecConfig(config);
factory.setMessageConverter(messageConverter);
factory.setAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE);
factory.setPubSubDomain(true);
factory.setSubscriptionDurable(true);
factory.setClientId("client-1234");
}
private void assertDefaultJcaConfig(JmsMessageEndpointManager container) {

View File

@@ -25,17 +25,17 @@ import java.util.List;
*/
public class JmsListenerContainerTestFactory implements JmsListenerContainerFactory<MessageListenerTestContainer> {
private final List<MessageListenerTestContainer> containers =
private final List<MessageListenerTestContainer> listenerContainers =
new ArrayList<MessageListenerTestContainer>();
public List<MessageListenerTestContainer> getContainers() {
return containers;
public List<MessageListenerTestContainer> getListenerContainers() {
return listenerContainers;
}
@Override
public MessageListenerTestContainer createMessageListenerContainer(JmsListenerEndpoint endpoint) {
public MessageListenerTestContainer createListenerContainer(JmsListenerEndpoint endpoint) {
MessageListenerTestContainer container = new MessageListenerTestContainer(endpoint);
this.containers.add(container);
this.listenerContainers.add(container);
return container;
}

View File

@@ -65,8 +65,8 @@ public class JmsListenerEndpointRegistrarTests {
registrar.setContainerFactory(containerFactory);
registrar.registerEndpoint(endpoint, null);
registrar.afterPropertiesSet();
assertNotNull("Container not created", registry.getContainer("some id"));
assertEquals(1, registry.getContainers().size());
assertNotNull("Container not created", registry.getListenerContainer("some id"));
assertEquals(1, registry.getListenerContainers().size());
}
@Test
@@ -87,8 +87,8 @@ public class JmsListenerEndpointRegistrarTests {
registrar.setContainerFactory(containerFactory);
registrar.registerEndpoint(endpoint);
registrar.afterPropertiesSet();
assertNotNull("Container not created", registry.getContainer("myEndpoint"));
assertEquals(1, registry.getContainers().size());
assertNotNull("Container not created", registry.getListenerContainer("myEndpoint"));
assertEquals(1, registry.getListenerContainers().size());
}
}

View File

@@ -36,27 +36,27 @@ public class JmsListenerEndpointRegistryTests {
@Test
public void createWithNullEndpoint() {
thrown.expect(IllegalArgumentException.class);
registry.createJmsListenerContainer(null, containerFactory);
registry.registerListenerContainer(null, containerFactory);
}
@Test
public void createWithNullEndpointId() {
thrown.expect(IllegalArgumentException.class);
registry.createJmsListenerContainer(new SimpleJmsListenerEndpoint(), containerFactory);
registry.registerListenerContainer(new SimpleJmsListenerEndpoint(), containerFactory);
}
@Test
public void createWithNullContainerFactory() {
thrown.expect(IllegalArgumentException.class);
registry.createJmsListenerContainer(createEndpoint("foo", "myDestination"), null);
registry.registerListenerContainer(createEndpoint("foo", "myDestination"), null);
}
@Test
public void createWithDuplicateEndpointId() {
registry.createJmsListenerContainer(createEndpoint("test", "queue"), containerFactory);
registry.registerListenerContainer(createEndpoint("test", "queue"), containerFactory);
thrown.expect(IllegalStateException.class);
registry.createJmsListenerContainer(createEndpoint("test", "queue"), containerFactory);
registry.registerListenerContainer(createEndpoint("test", "queue"), containerFactory);
}
private SimpleJmsListenerEndpoint createEndpoint(String id, String destinationName) {

View File

@@ -16,9 +16,6 @@
package org.springframework.jms.config;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import javax.jms.MessageListener;
import org.junit.Rule;
@@ -33,8 +30,10 @@ import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.jms.listener.endpoint.JmsActivationSpecConfig;
import org.springframework.jms.listener.endpoint.JmsMessageEndpointManager;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerEndpointTests {
@@ -53,10 +52,10 @@ public class JmsListenerEndpointTests {
endpoint.setConcurrency("5-10");
endpoint.setMessageListener(messageListener);
endpoint.setupMessageContainer(container);
endpoint.setupListenerContainer(container);
assertEquals("myQueue", container.getDestinationName());
assertEquals("foo = 'bar'", container.getMessageSelector());
assertEquals("mySubscription", container.getDurableSubscriptionName());
assertEquals("mySubscription", container.getSubscriptionName());
assertEquals(5, container.getConcurrentConsumers());
assertEquals(10, container.getMaxConcurrentConsumers());
assertEquals(messageListener, container.getMessageListener());
@@ -73,11 +72,11 @@ public class JmsListenerEndpointTests {
endpoint.setConcurrency("10");
endpoint.setMessageListener(messageListener);
endpoint.setupMessageContainer(container);
endpoint.setupListenerContainer(container);
JmsActivationSpecConfig config = container.getActivationSpecConfig();
assertEquals("myQueue", config.getDestinationName());
assertEquals("foo = 'bar'", config.getMessageSelector());
assertEquals("mySubscription", config.getDurableSubscriptionName());
assertEquals("mySubscription", config.getSubscriptionName());
assertEquals(10, config.getMaxConcurrency());
assertEquals(messageListener, container.getMessageListener());
}
@@ -90,7 +89,7 @@ public class JmsListenerEndpointTests {
endpoint.setConcurrency("5-10"); // simple implementation only support max value
endpoint.setMessageListener(messageListener);
endpoint.setupMessageContainer(container);
endpoint.setupListenerContainer(container);
assertEquals(10, new DirectFieldAccessor(container).getPropertyValue("concurrentConsumers"));
}
@@ -100,7 +99,7 @@ public class JmsListenerEndpointTests {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
thrown.expect(IllegalStateException.class);
endpoint.setupMessageContainer(container);
endpoint.setupListenerContainer(container);
}
@Test
@@ -110,7 +109,7 @@ public class JmsListenerEndpointTests {
endpoint.setMessageListener(new MessageListenerAdapter());
thrown.expect(IllegalArgumentException.class);
endpoint.setupMessageContainer(container);
endpoint.setupListenerContainer(container);
}

View File

@@ -145,7 +145,7 @@ public class JmsNamespaceHandlerTests {
assertNotNull("No factory registered with testJmsFactory id", factory);
DefaultMessageListenerContainer container =
factory.createMessageListenerContainer(createDummyEndpoint());
factory.createListenerContainer(createDummyEndpoint());
assertEquals("explicit connection factory not set",
context.getBean(EXPLICIT_CONNECTION_FACTORY), container.getConnectionFactory());
assertEquals("explicit destination resolver not set",
@@ -156,9 +156,8 @@ public class JmsNamespaceHandlerTests {
assertEquals("wrong concurrency", 3, container.getConcurrentConsumers());
assertEquals("wrong concurrency", 5, container.getMaxConcurrentConsumers());
assertEquals("wrong prefetch", 50, container.getMaxMessagesPerTask());
assertSame(context.getBean("testBackOff"),new DirectFieldAccessor(container).getPropertyValue("backOff"));
assertEquals("phase cannot be customized by the factory", Integer.MAX_VALUE, container.getPhase());
assertEquals("Wrong phase", 99, container.getPhase());
assertSame(context.getBean("testBackOff"), new DirectFieldAccessor(container).getPropertyValue("backOff"));
}
@Test
@@ -169,14 +168,14 @@ public class JmsNamespaceHandlerTests {
assertNotNull("No factory registered with testJcaFactory id", factory);
JmsMessageEndpointManager container =
factory.createMessageListenerContainer(createDummyEndpoint());
factory.createListenerContainer(createDummyEndpoint());
assertEquals("explicit resource adapter not set",
context.getBean("testResourceAdapter"),container.getResourceAdapter());
assertEquals("explicit message converter not set",
context.getBean("testMessageConverter"), container.getActivationSpecConfig().getMessageConverter());
assertEquals("wrong concurrency", 5, container.getActivationSpecConfig().getMaxConcurrency());
assertEquals("Wrong prefetch", 50, container.getActivationSpecConfig().getPrefetchSize());
assertEquals("phase cannot be customized by the factory", Integer.MAX_VALUE, container.getPhase());
assertEquals("Wrong phase", 77, container.getPhase());
}
@Test

View File

@@ -23,7 +23,6 @@ import org.springframework.jms.listener.MessageListenerContainer;
import org.springframework.jms.support.converter.MessageConverter;
/**
*
* @author Stephane Nicoll
*/
public class MessageListenerTestContainer
@@ -57,17 +56,15 @@ public class MessageListenerTestContainer
@Override
public void start() throws JmsException {
if (!initializationInvoked) {
throw new IllegalStateException("afterPropertiesSet should have been invoked before start on " + this);
}
if (startInvoked) {
throw new IllegalStateException("Start already invoked on " + this);
}
startInvoked = true;
}
@Override
public boolean isRunning() {
return startInvoked && !stopInvoked;
}
@Override
public void stop() throws JmsException {
if (stopInvoked) {
@@ -77,8 +74,28 @@ public class MessageListenerTestContainer
}
@Override
public void setupMessageListener(Object messageListener) {
public boolean isRunning() {
return startInvoked && !stopInvoked;
}
@Override
public int getPhase() {
return 0;
}
@Override
public boolean isAutoStartup() {
return true;
}
@Override
public void stop(Runnable callback) {
stopInvoked = true;
callback.run();
}
@Override
public void setupMessageListener(Object messageListener) {
}
@Override
@@ -93,10 +110,6 @@ public class MessageListenerTestContainer
@Override
public void afterPropertiesSet() {
if (!startInvoked) {
throw new IllegalStateException("Start should have been invoked before " +
"afterPropertiesSet on " + this);
}
initializationInvoked = true;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-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.
@@ -62,9 +62,7 @@ public class DefaultJmsActivationSpecFactoryTests extends TestCase {
Destination destination = new StubQueue();
DestinationResolver destinationResolver = mock(DestinationResolver.class);
given(destinationResolver.resolveDestinationName(null, "destinationname",
false)).willReturn(destination);
given(destinationResolver.resolveDestinationName(null, "destinationname", false)).willReturn(destination);
DefaultJmsActivationSpecFactory activationSpecFactory = new DefaultJmsActivationSpecFactory();
activationSpecFactory.setDestinationResolver(destinationResolver);