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

@ -66,7 +66,9 @@ import org.springframework.context.annotation.Import;
* }</pre> * }</pre>
* *
* The container factory to use is identified by the {@link JmsListener#containerFactory() containerFactory} * The container factory to use is identified by the {@link JmsListener#containerFactory() containerFactory}
* attribute defining the name of the {@code JmsListenerContainerFactory} bean to use. * attribute defining the name of the {@code JmsListenerContainerFactory} bean to use. When none
* is set a {@code JmsListenerContainerFactory} bean with name {@code jmsListenerContainerFactory} is
* assumed to be present.
* *
* <p>the following configuration would ensure that every time a {@link javax.jms.Message} * <p>the following configuration would ensure that every time a {@link javax.jms.Message}
* is received on the {@link javax.jms.Destination} named "myQueue", {@code MyService.process()} * is received on the {@link javax.jms.Destination} named "myQueue", {@code MyService.process()}
@ -118,9 +120,8 @@ import org.springframework.context.annotation.Import;
* <p>When more control is desired, a {@code @Configuration} class may implement * <p>When more control is desired, a {@code @Configuration} class may implement
* {@link JmsListenerConfigurer}. This allows access to the underlying * {@link JmsListenerConfigurer}. This allows access to the underlying
* {@link org.springframework.jms.config.JmsListenerEndpointRegistrar JmsListenerEndpointRegistrar} * {@link org.springframework.jms.config.JmsListenerEndpointRegistrar JmsListenerEndpointRegistrar}
* instance. The following example demonstrates how to specify a default * instance. The following example demonstrates how to specify an explicit default
* {@code JmsListenerContainerFactory} so that {@link JmsListener#containerFactory()} may be * {@code JmsListenerContainerFactory}
* omitted for endpoints willing to use the <em>default</em> container factory.
* *
* <pre class="code"> * <pre class="code">
* &#064;Configuration * &#064;Configuration
@ -128,7 +129,7 @@ import org.springframework.context.annotation.Import;
* public class AppConfig implements JmsListenerConfigurer { * public class AppConfig implements JmsListenerConfigurer {
* &#064;Override * &#064;Override
* public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { * public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
* registrar.setDefaultContainerFactory(myJmsListenerContainerFactory()); * registrar.setContainerFactory(myJmsListenerContainerFactory());
* } * }
* *
* &#064;Bean * &#064;Bean
@ -146,7 +147,7 @@ import org.springframework.context.annotation.Import;
* configuration: * configuration:
* <pre class="code"> * <pre class="code">
* {@code <beans> * {@code <beans>
* <jms:annotation-driven default-container-factory="myJmsListenerContainerFactory"/> * <jms:annotation-driven container-factory="myJmsListenerContainerFactory"/>
* *
* <bean id="myJmsListenerContainerFactory" * <bean id="myJmsListenerContainerFactory"
* class="org.springframework.jms.config.DefaultJmsListenerContainerFactory"> * class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">

View File

@ -28,8 +28,10 @@ import org.springframework.messaging.handler.annotation.MessageMapping;
* Annotation that marks a method to be the target of a JMS message * Annotation that marks a method to be the target of a JMS message
* listener on the specified {@link #destination()}. The {@link #containerFactory()} * listener on the specified {@link #destination()}. The {@link #containerFactory()}
* identifies the {@link org.springframework.jms.config.JmsListenerContainerFactory * identifies the {@link org.springframework.jms.config.JmsListenerContainerFactory
* JmsListenerContainerFactory} to use to build the jms listener container. It may * JmsListenerContainerFactory} to use to build the jms listener container. If not
* be omitted as long as a <em>default</em> container factory has been defined. * set, a <em>default</em> container factory is assumed to be available with a bean
* name of {@code jmsListenerContainerFactory} unless an explicit default has been
* provided through configuration.
* *
* <p>Processing of {@code @JmsListener} annotations is performed by * <p>Processing of {@code @JmsListener} annotations is performed by
* registering a {@link JmsListenerAnnotationBeanPostProcessor}. This can be * registering a {@link JmsListenerAnnotationBeanPostProcessor}. This can be

View File

@ -73,13 +73,18 @@ import org.springframework.util.StringUtils;
public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered, public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered,
ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> { ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {
/**
* The bean name of the default {@link JmsListenerContainerFactory}
*/
static final String DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME = "jmsListenerContainerFactory";
private final AtomicInteger counter = new AtomicInteger(); private final AtomicInteger counter = new AtomicInteger();
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private JmsListenerEndpointRegistry endpointRegistry; private JmsListenerEndpointRegistry endpointRegistry;
private JmsListenerContainerFactory<?> defaultContainerFactory; private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME;
private final JmsHandlerMethodFactoryAdapter jmsHandlerMethodFactory = new JmsHandlerMethodFactoryAdapter(); private final JmsHandlerMethodFactoryAdapter jmsHandlerMethodFactory = new JmsHandlerMethodFactoryAdapter();
@ -99,12 +104,12 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor
} }
/** /**
* Set the default {@link JmsListenerContainerFactory} to use in case a * Set the name of the {@link JmsListenerContainerFactory} to use by default.
* {@link JmsListener} does not define any. * <p/>If none is specified, {@value #DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME}
* {@linkplain JmsListener#containerFactory() containerFactory} * is assumed to be defined.
*/ */
public void setDefaultContainerFactory(JmsListenerContainerFactory<?> defaultContainerFactory) { public void setContainerFactoryBeanName(String containerFactoryBeanName) {
this.defaultContainerFactory = defaultContainerFactory; this.containerFactoryBeanName = containerFactoryBeanName;
} }
/** /**
@ -209,6 +214,9 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor
for (JmsListenerConfigurer configurer : instances.values()) { for (JmsListenerConfigurer configurer : instances.values()) {
configurer.configureJmsListeners(registrar); configurer.configureJmsListeners(registrar);
} }
registrar.setApplicationContext(this.applicationContext);
if (registrar.getEndpointRegistry() == null) { if (registrar.getEndpointRegistry() == null) {
if (endpointRegistry == null) { if (endpointRegistry == null) {
endpointRegistry = applicationContext endpointRegistry = applicationContext
@ -217,10 +225,13 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor
} }
registrar.setEndpointRegistry(endpointRegistry); registrar.setEndpointRegistry(endpointRegistry);
} }
if (registrar.getDefaultContainerFactory() == null && defaultContainerFactory != null) {
registrar.setDefaultContainerFactory(defaultContainerFactory); if (this.containerFactoryBeanName != null) {
registrar.setContainerFactoryBeanName(this.containerFactoryBeanName);
} }
// Set the custom handler method factory once resolved by the configurer
JmsHandlerMethodFactory handlerMethodFactory = registrar.getJmsHandlerMethodFactory(); JmsHandlerMethodFactory handlerMethodFactory = registrar.getJmsHandlerMethodFactory();
if (handlerMethodFactory != null) { if (handlerMethodFactory != null) {
this.jmsHandlerMethodFactory.setJmsHandlerMethodFactory(handlerMethodFactory); this.jmsHandlerMethodFactory.setJmsHandlerMethodFactory(handlerMethodFactory);
@ -235,7 +246,6 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor
} }
} }
private String getEndpointId(JmsListener jmsListener) { private String getEndpointId(JmsListener jmsListener) {
if (StringUtils.hasText(jmsListener.id())) { if (StringUtils.hasText(jmsListener.id())) {
return jmsListener.id(); return jmsListener.id();
@ -267,7 +277,7 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor
private JmsHandlerMethodFactory getJmsHandlerMethodFactory() { private JmsHandlerMethodFactory getJmsHandlerMethodFactory() {
if (jmsHandlerMethodFactory == null) { if (jmsHandlerMethodFactory == null) {
jmsHandlerMethodFactory= createDefaultJmsHandlerMethodFactory(); jmsHandlerMethodFactory = createDefaultJmsHandlerMethodFactory();
} }
return jmsHandlerMethodFactory; return jmsHandlerMethodFactory;
} }

View File

@ -64,10 +64,12 @@ final class AnnotationDrivenJmsBeanDefinitionParser implements BeanDefinitionPar
else { else {
registerDefaultEndpointRegistry(source, parserContext); registerDefaultEndpointRegistry(source, parserContext);
} }
String defaultContainerFactory = element.getAttribute("default-container-factory");
if (StringUtils.hasText(defaultContainerFactory)) { String containerFactory = element.getAttribute("container-factory");
builder.addPropertyReference("defaultContainerFactory", defaultContainerFactory); if (StringUtils.hasText(containerFactory)) {
builder.addPropertyValue("containerFactoryBeanName", containerFactory);
} }
String handlerMethodFactory = element.getAttribute("handler-method-factory"); String handlerMethodFactory = element.getAttribute("handler-method-factory");
if (StringUtils.hasText(handlerMethodFactory)) { if (StringUtils.hasText(handlerMethodFactory)) {
builder.addPropertyReference("jmsHandlerMethodFactory", handlerMethodFactory); builder.addPropertyReference("jmsHandlerMethodFactory", handlerMethodFactory);

View File

@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -30,14 +32,18 @@ import org.springframework.util.Assert;
* @since 4.1 * @since 4.1
* @see org.springframework.jms.annotation.JmsListenerConfigurer * @see org.springframework.jms.annotation.JmsListenerConfigurer
*/ */
public class JmsListenerEndpointRegistrar implements InitializingBean { public class JmsListenerEndpointRegistrar implements ApplicationContextAware, InitializingBean {
private JmsListenerEndpointRegistry endpointRegistry; private JmsListenerEndpointRegistry endpointRegistry;
private JmsListenerContainerFactory<?> defaultContainerFactory; private String containerFactoryBeanName;
private JmsListenerContainerFactory<?> containerFactory;
private JmsHandlerMethodFactory jmsHandlerMethodFactory; private JmsHandlerMethodFactory jmsHandlerMethodFactory;
private ApplicationContext applicationContext;
private final List<JmsListenerEndpointDescriptor> endpointDescriptors private final List<JmsListenerEndpointDescriptor> endpointDescriptors
= new ArrayList<JmsListenerEndpointDescriptor>(); = new ArrayList<JmsListenerEndpointDescriptor>();
@ -57,20 +63,24 @@ public class JmsListenerEndpointRegistrar implements InitializingBean {
} }
/** /**
* Set the default {@link JmsListenerContainerFactory} to use in case a * Set the bean name of the {@link JmsListenerContainerFactory} to use in
* {@link JmsListenerEndpoint} is registered with a {@code null} container * case a {@link JmsListenerEndpoint} is registered with a {@code null}
* factory. * container factory. Alternatively, the container factory instance can
* be registered directly, see {@link #setContainerFactory(JmsListenerContainerFactory)}
*/ */
public void setDefaultContainerFactory(JmsListenerContainerFactory<?> defaultContainerFactory) { public void setContainerFactoryBeanName(String containerFactoryBeanName) {
this.defaultContainerFactory = defaultContainerFactory; this.containerFactoryBeanName = containerFactoryBeanName;
} }
/** /**
* Return the {@link JmsListenerContainerFactory} to use if none has been * Set the {@link JmsListenerContainerFactory} to use in case a
* defined for a particular endpoint or {@code null} if no default is set. * {@link JmsListenerEndpoint} is registered with a {@code null} container
* factory.
* <p>Alternatively, the bean name of the {@link JmsListenerContainerFactory}
* to use can be specified for a lazy lookup, see {@see #setContainerFactoryBeanName}
*/ */
public JmsListenerContainerFactory<?> getDefaultContainerFactory() { public void setContainerFactory(JmsListenerContainerFactory<?> containerFactory) {
return defaultContainerFactory; this.containerFactory = containerFactory;
} }
/** /**
@ -92,6 +102,11 @@ public class JmsListenerEndpointRegistrar implements InitializingBean {
return jmsHandlerMethodFactory; return jmsHandlerMethodFactory;
} }
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/** /**
* Register a new {@link JmsListenerEndpoint} alongside the {@link JmsListenerContainerFactory} * Register a new {@link JmsListenerEndpoint} alongside the {@link JmsListenerContainerFactory}
* to use to create the underlying container. * to use to create the underlying container.
@ -109,7 +124,7 @@ public class JmsListenerEndpointRegistrar implements InitializingBean {
* Register a new {@link JmsListenerEndpoint} using the default {@link JmsListenerContainerFactory} * Register a new {@link JmsListenerEndpoint} using the default {@link JmsListenerContainerFactory}
* to create the underlying container. * to create the underlying container.
* *
* @see #setDefaultContainerFactory(JmsListenerContainerFactory) * @see #setContainerFactory(JmsListenerContainerFactory)
* @see #registerEndpoint(JmsListenerEndpoint, JmsListenerContainerFactory) * @see #registerEndpoint(JmsListenerEndpoint, JmsListenerContainerFactory)
*/ */
public void registerEndpoint(JmsListenerEndpoint endpoint) { public void registerEndpoint(JmsListenerEndpoint endpoint) {
@ -118,6 +133,7 @@ public class JmsListenerEndpointRegistrar implements InitializingBean {
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
Assert.notNull(applicationContext, "ApplicationContext must not be null");
startAllEndpoints(); startAllEndpoints();
} }
@ -132,8 +148,13 @@ public class JmsListenerEndpointRegistrar implements InitializingBean {
if (descriptor.containerFactory != null) { if (descriptor.containerFactory != null) {
return descriptor.containerFactory; return descriptor.containerFactory;
} }
else if (defaultContainerFactory != null) { else if (this.containerFactory != null) {
return defaultContainerFactory; return this.containerFactory;
}
else if (this.containerFactoryBeanName != null) {
this.containerFactory = applicationContext.getBean(
this.containerFactoryBeanName, JmsListenerContainerFactory.class);
return this.containerFactory; // Consider changing this if live change of the factory is required
} }
else { else {
throw new IllegalStateException("Could not resolve the " throw new IllegalStateException("Could not resolve the "

View File

@ -43,13 +43,15 @@
</xsd:appinfo> </xsd:appinfo>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
<xsd:attribute name="default-container-factory" type="xsd:string" use="optional"> <xsd:attribute name="container-factory" type="xsd:string" use="optional">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
Specifies the default org.springframework.jms.config.JmsListenerContainerFactory instance to Specifies the org.springframework.jms.config.JmsListenerContainerFactory instance to
use to create the container for a jms listener endpoint that does not define a specific use to create the container for a jms listener endpoint that does not define a specific
factory. This permits in practice to omit the "containerFactory" attribute of the JmsListener factory. This permits in practice to omit the "containerFactory" attribute of the JmsListener
annotation. If not provided, each endpoint must define the container factory to use. annotation. This attribute is not required as each endpoint may define the factory to use and,
as a convenience, the JmsListenerContainerFactory with name 'jmsListenerContainerFactory' is
looked up by default.
]]></xsd:documentation> ]]></xsd:documentation>
<xsd:appinfo> <xsd:appinfo>
<tool:annotation kind="ref"> <tool:annotation kind="ref">

View File

@ -59,17 +59,21 @@ public abstract class AbstractJmsAnnotationDrivenTests {
public abstract void customConfiguration(); public abstract void customConfiguration();
@Test @Test
public abstract void defaultContainerFactoryConfiguration(); public abstract void explicitContainerFactory();
@Test
public abstract void defaultContainerFactory();
@Test @Test
public abstract void jmsHandlerMethodFactoryConfiguration() throws JMSException; 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) { public void testSampleConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory = JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class); context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory simpleFactory = JmsListenerContainerTestFactory simpleFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class); context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size()); assertEquals(1, defaultFactory.getContainers().size());
@ -79,7 +83,7 @@ public abstract class AbstractJmsAnnotationDrivenTests {
@Component @Component
static class SampleBean { static class SampleBean {
@JmsListener(containerFactory = "defaultFactory", destination = "myQueue") @JmsListener(destination = "myQueue")
public void defaultHandle(String msg) { 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) { public void testFullConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory simpleFactory = JmsListenerContainerTestFactory simpleFactory =
@ -116,11 +122,12 @@ public abstract class AbstractJmsAnnotationDrivenTests {
/** /**
* Test for {@link CustomBean} and an manually endpoint registered * 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) { public void testCustomConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory = JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class); context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory customFactory = JmsListenerContainerTestFactory customFactory =
context.getBean("customFactory", JmsListenerContainerTestFactory.class); context.getBean("customFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size()); assertEquals(1, defaultFactory.getContainers().size());
@ -150,11 +157,22 @@ public abstract class AbstractJmsAnnotationDrivenTests {
/** /**
* Test for {@link DefaultBean} that does not define the container * 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) { public void testDefaultContainerFactoryConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory = JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class); context.getBean("jmsListenerContainerFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size()); assertEquals(1, defaultFactory.getContainers().size());
} }

View File

@ -24,7 +24,6 @@ import org.junit.Test;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerEndpointRegistrar; import org.springframework.jms.config.JmsListenerEndpointRegistrar;
import org.springframework.jms.config.SimpleJmsListenerEndpoint; import org.springframework.jms.config.SimpleJmsListenerEndpoint;
import org.springframework.jms.listener.adapter.ListenerExecutionFailedException; import org.springframework.jms.listener.adapter.ListenerExecutionFailedException;
@ -62,9 +61,16 @@ public class AnnotationDrivenNamespaceTests extends AbstractJmsAnnotationDrivenT
@Override @Override
@Test @Test
public void defaultContainerFactoryConfiguration() { public void explicitContainerFactory() {
ApplicationContext context = new ClassPathXmlApplicationContext( ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-custom-container-factory.xml", getClass()); "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); testDefaultContainerFactoryConfiguration(context);
} }
@ -82,23 +88,18 @@ public class AnnotationDrivenNamespaceTests extends AbstractJmsAnnotationDrivenT
private MessageListener messageListener; private MessageListener messageListener;
private JmsListenerContainerFactory<?> containerFactory;
@Override @Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint(); SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myCustomEndpointId"); endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue"); endpoint.setDestination("myQueue");
endpoint.setMessageListener(messageListener); endpoint.setMessageListener(messageListener);
registrar.registerEndpoint(endpoint, containerFactory); registrar.registerEndpoint(endpoint);
} }
public void setMessageListener(MessageListener messageListener) { public void setMessageListener(MessageListener messageListener) {
this.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 @Test
public void sampleConfiguration() { public void sampleConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext( ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsConfig.class, SampleBean.class); EnableJmsSampleConfig.class, SampleBean.class);
testSampleConfiguration(context); testSampleConfiguration(context);
} }
@ -62,7 +62,7 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Test @Test
public void fullConfiguration() { public void fullConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext( ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsConfig.class, FullBean.class); EnableJmsFullConfig.class, FullBean.class);
testFullConfiguration(context); testFullConfiguration(context);
} }
@ -76,7 +76,15 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Override @Override
@Test @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( ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, DefaultBean.class); EnableJmsDefaultContainerFactoryConfig.class, DefaultBean.class);
testDefaultContainerFactoryConfiguration(context); testDefaultContainerFactoryConfiguration(context);
@ -98,15 +106,15 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
thrown.expect(BeanCreationException.class); thrown.expect(BeanCreationException.class);
thrown.expectMessage("customFactory"); // Not found thrown.expectMessage("customFactory"); // Not found
new AnnotationConfigApplicationContext( new AnnotationConfigApplicationContext(
EnableJmsConfig.class, CustomBean.class); EnableJmsSampleConfig.class, CustomBean.class);
} }
@EnableJms @EnableJms
@Configuration @Configuration
static class EnableJmsConfig { static class EnableJmsSampleConfig {
@Bean @Bean
public JmsListenerContainerTestFactory defaultFactory() { public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory(); return new JmsListenerContainerTestFactory();
} }
@ -116,12 +124,19 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
} }
} }
@EnableJms
@Configuration @Configuration
@Import(EnableJmsConfig.class) static class EnableJmsFullConfig {
static class EnableJmsCustomConfig implements JmsListenerConfigurer {
@Autowired @Bean
private EnableJmsConfig jmsConfig; public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@EnableJms
static class EnableJmsCustomConfig implements JmsListenerConfigurer {
@Override @Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
@ -132,7 +147,12 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
endpoint.setId("myCustomEndpointId"); endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue"); endpoint.setDestination("myQueue");
endpoint.setMessageListener(simpleMessageListener()); endpoint.setMessageListener(simpleMessageListener());
registrar.registerEndpoint(endpoint, jmsConfig.defaultFactory()); registrar.registerEndpoint(endpoint);
}
@Bean
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
} }
@Bean @Bean
@ -152,20 +172,32 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
} }
@Configuration @Configuration
@Import(EnableJmsConfig.class) @EnableJms
static class EnableJmsDefaultContainerFactoryConfig implements JmsListenerConfigurer { static class EnableJmsCustomContainerFactoryConfig implements JmsListenerConfigurer {
@Autowired
private EnableJmsConfig jmsConfig;
@Override @Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setDefaultContainerFactory(jmsConfig.defaultFactory()); registrar.setContainerFactory(simpleFactory());
}
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
} }
} }
@Configuration @Configuration
@Import(EnableJmsConfig.class) @EnableJms
static class EnableJmsDefaultContainerFactoryConfig {
@Bean
public JmsListenerContainerTestFactory jmsListenerContainerFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@EnableJms
static class EnableJmsHandlerMethodFactoryConfig implements JmsListenerConfigurer { static class EnableJmsHandlerMethodFactoryConfig implements JmsListenerConfigurer {
@Override @Override
@ -179,6 +211,11 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
factory.setValidator(new TestValidator()); factory.setValidator(new TestValidator());
return factory; return factory;
} }
@Bean
public JmsListenerContainerTestFactory defaultFactory() {
return new JmsListenerContainerTestFactory();
}
} }
} }

View File

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

View File

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

View File

@ -7,11 +7,11 @@
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.1.xsd"> http://www.springframework.org/schema/jms/spring-jms-4.1.xsd">
<jms:annotation-driven default-container-factory="defaultFactory"/> <jms:annotation-driven container-factory="simpleFactory"/>
<bean class="org.springframework.jms.annotation.AbstractJmsAnnotationDrivenTests$DefaultBean"/> <bean class="org.springframework.jms.annotation.AbstractJmsAnnotationDrivenTests$DefaultBean"/>
<bean id="defaultFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/> <bean id="simpleFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/>
</beans> </beans>

View File

@ -13,14 +13,13 @@
<bean id="customRegistry" class="org.springframework.jms.config.JmsListenerEndpointRegistry"/> <bean id="customRegistry" class="org.springframework.jms.config.JmsListenerEndpointRegistry"/>
<bean id="defaultFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/> <bean id="jmsListenerContainerFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/>
<bean id="customFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/> <bean id="customFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/>
<bean id="simpleMessageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"/> <bean id="simpleMessageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"/>
<bean class="org.springframework.jms.annotation.AnnotationDrivenNamespaceTests$CustomJmsListenerConfigurer"> <bean class="org.springframework.jms.annotation.AnnotationDrivenNamespaceTests$CustomJmsListenerConfigurer">
<property name="messageListener" ref="simpleMessageListener"/> <property name="messageListener" ref="simpleMessageListener"/>
<property name="containerFactory" ref="defaultFactory"/>
</bean> </bean>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.1.xsd">
<jms:annotation-driven/>
<bean class="org.springframework.jms.annotation.AbstractJmsAnnotationDrivenTests$DefaultBean"/>
<bean id="jmsListenerContainerFactory"
class="org.springframework.jms.config.JmsListenerContainerTestFactory"/>
</beans>

View File

@ -11,7 +11,7 @@
<bean class="org.springframework.jms.annotation.AbstractJmsAnnotationDrivenTests$SampleBean"/> <bean class="org.springframework.jms.annotation.AbstractJmsAnnotationDrivenTests$SampleBean"/>
<bean id="defaultFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/> <bean id="jmsListenerContainerFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/>
<bean id="simpleFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/> <bean id="simpleFactory" class="org.springframework.jms.config.JmsListenerContainerTestFactory"/>