Default JmsListenerContainerFactory lookup

Prior to this commit, the default JmsListenerContainerFactory to use
must be explicitly set. Since having a single container factory is a
fairly common use case, we look up the default one automatically
using the bean name "jmsListenerContainerFactory".

It is still possible to provide an explicit default but since it refers
more to "the" container factory to use, the parameter has been
renamed to "containerFactory" which is shorter and more explicit.

The lookup strategy is lazy: if all endpoints are providing an
explicit container factory and no container factory with the
"jmsListenerContainerFactory" bean name exists, no exception
will be thrown.

Issue : SPR-11706
This commit is contained in:
Stephane Nicoll
2014-04-24 10:31:44 +03:00
parent 08f0395033
commit 4b0aba63df
15 changed files with 195 additions and 81 deletions

View File

@@ -59,17 +59,21 @@ public abstract class AbstractJmsAnnotationDrivenTests {
public abstract void customConfiguration();
@Test
public abstract void defaultContainerFactoryConfiguration();
public abstract void explicitContainerFactory();
@Test
public abstract void defaultContainerFactory();
@Test
public abstract void jmsHandlerMethodFactoryConfiguration() throws JMSException;
/**
* Test for {@link SampleBean} discovery.
* Test for {@link SampleBean} discovery. If a factory with the default name
* is set, an endpoint will use it automatically
*/
public void testSampleConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory simpleFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
@@ -79,7 +83,7 @@ public abstract class AbstractJmsAnnotationDrivenTests {
@Component
static class SampleBean {
@JmsListener(containerFactory = "defaultFactory", destination = "myQueue")
@JmsListener(destination = "myQueue")
public void defaultHandle(String msg) {
}
@@ -89,7 +93,9 @@ public abstract class AbstractJmsAnnotationDrivenTests {
}
/**
* Test for {@link FullBean} discovery.
* Test for {@link FullBean} discovery. In this case, no default is set because
* all endpoints provide a default registry. This shows that the default factory
* is only retrieved if it needs to be.
*/
public void testFullConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory simpleFactory =
@@ -116,11 +122,12 @@ public abstract class AbstractJmsAnnotationDrivenTests {
/**
* Test for {@link CustomBean} and an manually endpoint registered
* with "myCustomEndpointId".
* with "myCustomEndpointId". The custom endpoint does not provide
* any factory so it's registered with the default one
*/
public void testCustomConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory customFactory =
context.getBean("customFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
@@ -150,11 +157,22 @@ public abstract class AbstractJmsAnnotationDrivenTests {
/**
* Test for {@link DefaultBean} that does not define the container
* factory to use as a default is registered.
* factory to use as a default is registered with an explicit
* default.
*/
public void testExplicitContainerFactoryConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
}
/**
* Test for {@link DefaultBean} that does not define the container
* factory to use as a default is registered with the default name.
*/
public void testDefaultContainerFactoryConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
}

View File

@@ -24,7 +24,6 @@ import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerEndpointRegistrar;
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
import org.springframework.jms.listener.adapter.ListenerExecutionFailedException;
@@ -62,9 +61,16 @@ public class AnnotationDrivenNamespaceTests extends AbstractJmsAnnotationDrivenT
@Override
@Test
public void defaultContainerFactoryConfiguration() {
public void explicitContainerFactory() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-custom-container-factory.xml", getClass());
testExplicitContainerFactoryConfiguration(context);
}
@Override
public void defaultContainerFactory() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-default-container-factory.xml", getClass());
testDefaultContainerFactoryConfiguration(context);
}
@@ -82,23 +88,18 @@ public class AnnotationDrivenNamespaceTests extends AbstractJmsAnnotationDrivenT
private MessageListener messageListener;
private JmsListenerContainerFactory<?> containerFactory;
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue");
endpoint.setMessageListener(messageListener);
registrar.registerEndpoint(endpoint, containerFactory);
registrar.registerEndpoint(endpoint);
}
public void setMessageListener(MessageListener messageListener) {
this.messageListener = messageListener;
}
public void setContainerFactory(JmsListenerContainerFactory<?> containerFactory) {
this.containerFactory = containerFactory;
}
}
}

View File

@@ -54,7 +54,7 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Test
public void sampleConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsConfig.class, SampleBean.class);
EnableJmsSampleConfig.class, SampleBean.class);
testSampleConfiguration(context);
}
@@ -62,7 +62,7 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Test
public void fullConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsConfig.class, FullBean.class);
EnableJmsFullConfig.class, FullBean.class);
testFullConfiguration(context);
}
@@ -76,7 +76,15 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Override
@Test
public void defaultContainerFactoryConfiguration() {
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);
@@ -98,15 +106,15 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
thrown.expect(BeanCreationException.class);
thrown.expectMessage("customFactory"); // Not found
new AnnotationConfigApplicationContext(
EnableJmsConfig.class, CustomBean.class);
EnableJmsSampleConfig.class, CustomBean.class);
}
@EnableJms
@Configuration
static class EnableJmsConfig {
static class EnableJmsSampleConfig {
@Bean
public JmsListenerContainerTestFactory defaultFactory() {
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
}
@@ -116,12 +124,19 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
}
}
@EnableJms
@Configuration
@Import(EnableJmsConfig.class)
static class EnableJmsCustomConfig implements JmsListenerConfigurer {
static class EnableJmsFullConfig {
@Autowired
private EnableJmsConfig jmsConfig;
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@EnableJms
static class EnableJmsCustomConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
@@ -132,7 +147,12 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue");
endpoint.setMessageListener(simpleMessageListener());
registrar.registerEndpoint(endpoint, jmsConfig.defaultFactory());
registrar.registerEndpoint(endpoint);
}
@Bean
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
}
@Bean
@@ -152,20 +172,32 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
}
@Configuration
@Import(EnableJmsConfig.class)
static class EnableJmsDefaultContainerFactoryConfig implements JmsListenerConfigurer {
@Autowired
private EnableJmsConfig jmsConfig;
@EnableJms
static class EnableJmsCustomContainerFactoryConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setDefaultContainerFactory(jmsConfig.defaultFactory());
registrar.setContainerFactory(simpleFactory());
}
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@Import(EnableJmsConfig.class)
@EnableJms
static class EnableJmsDefaultContainerFactoryConfig {
@Bean
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@EnableJms
static class EnableJmsHandlerMethodFactoryConfig implements JmsListenerConfigurer {
@Override
@@ -179,6 +211,11 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
factory.setValidator(new TestValidator());
return factory;
}
@Bean
public JmsListenerContainerTestFactory defaultFactory() {
return new JmsListenerContainerTestFactory();
}
}
}

View File

@@ -113,7 +113,7 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
public JmsListenerAnnotationBeanPostProcessor postProcessor() {
JmsListenerAnnotationBeanPostProcessor postProcessor = new JmsListenerAnnotationBeanPostProcessor();
postProcessor.setEndpointRegistry(jmsListenerEndpointRegistry());
postProcessor.setDefaultContainerFactory(testFactory());
postProcessor.setContainerFactoryBeanName("testFactory");
return postProcessor;
}

View File

@@ -23,6 +23,8 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.context.support.StaticApplicationContext;
/**
*
* @author Stephane Nicoll
@@ -41,6 +43,7 @@ public class JmsListenerEndpointRegistrarTests {
@Before
public void setup() {
registrar.setEndpointRegistry(registry);
registrar.setApplicationContext(new StaticApplicationContext());
}
@Test
@@ -59,7 +62,7 @@ public class JmsListenerEndpointRegistrarTests {
public void registerNullContainerFactoryIsAllowed() throws Exception {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("some id");
registrar.setDefaultContainerFactory(containerFactory);
registrar.setContainerFactory(containerFactory);
registrar.registerEndpoint(endpoint, null);
registrar.afterPropertiesSet();
assertNotNull("Container not created", registry.getContainer("some id"));
@@ -81,7 +84,7 @@ public class JmsListenerEndpointRegistrarTests {
public void registerContainerWithoutFactory() throws Exception {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myEndpoint");
registrar.setDefaultContainerFactory(containerFactory);
registrar.setContainerFactory(containerFactory);
registrar.registerEndpoint(endpoint);
registrar.afterPropertiesSet();
assertNotNull("Container not created", registry.getContainer("myEndpoint"));