diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java index 8719d5a0f32..5509dd53aba 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java @@ -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. @@ -23,13 +23,14 @@ import java.util.TimeZone; import java.util.concurrent.ScheduledExecutorService; import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ApplicationListener; import org.springframework.context.EmbeddedValueResolverAware; -import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.scheduling.TaskScheduler; @@ -57,7 +58,7 @@ import org.springframework.util.StringValueResolver; *

Auto-detects any {@link SchedulingConfigurer} instances in the container, * allowing for customization of the scheduler to be used or for fine-grained control * over task registration (e.g. registration of {@link Trigger} tasks. - * See @{@link EnableScheduling} Javadoc for complete usage details. + * See the @{@link EnableScheduling} javadocs for complete usage details. * * @author Mark Fisher * @author Juergen Hoeller @@ -70,18 +71,23 @@ import org.springframework.util.StringValueResolver; * @see org.springframework.scheduling.config.ScheduledTaskRegistrar */ public class ScheduledAnnotationBeanPostProcessor - implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, ApplicationContextAware, - ApplicationListener, DisposableBean { + implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanFactoryAware, + SmartInitializingSingleton, DisposableBean { private Object scheduler; private StringValueResolver embeddedValueResolver; - private ApplicationContext applicationContext; + private ListableBeanFactory beanFactory; private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar(); + @Override + public int getOrder() { + return LOWEST_PRECEDENCE; + } + /** * Set the {@link org.springframework.scheduling.TaskScheduler} that will invoke * the scheduled methods, or a {@link java.util.concurrent.ScheduledExecutorService} @@ -96,16 +102,63 @@ public class ScheduledAnnotationBeanPostProcessor this.embeddedValueResolver = resolver; } + /** + * Making a {@link BeanFactory} available is optional; if not set, + * {@link SchedulingConfigurer} beans won't get autodetected and + * a {@link #setScheduler scheduler} has to be explicitly configured. + */ @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = (beanFactory instanceof ListableBeanFactory ? (ListableBeanFactory) beanFactory : null); } - @Override - public int getOrder() { - return LOWEST_PRECEDENCE; + /** + * @deprecated as of Spring 4.1, in favor of {@link #setBeanFactory} + */ + @Deprecated + public void setApplicationContext(ApplicationContext applicationContext) { + this.beanFactory = applicationContext; } + + @Override + public void afterSingletonsInstantiated() { + if (this.scheduler != null) { + this.registrar.setScheduler(this.scheduler); + } + + if (this.beanFactory != null) { + Map configurers = this.beanFactory.getBeansOfType(SchedulingConfigurer.class); + for (SchedulingConfigurer configurer : configurers.values()) { + configurer.configureTasks(this.registrar); + } + } + + if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) { + Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type"); + Map schedulers = new HashMap(); + schedulers.putAll(this.beanFactory.getBeansOfType(TaskScheduler.class)); + schedulers.putAll(this.beanFactory.getBeansOfType(ScheduledExecutorService.class)); + if (schedulers.size() == 0) { + // do nothing -> fall back to default scheduler + } + else if (schedulers.size() == 1) { + this.registrar.setScheduler(schedulers.values().iterator().next()); + } + else if (schedulers.size() >= 2){ + throw new IllegalStateException( + "More than one TaskScheduler and/or ScheduledExecutorService " + + "exist within the context. Remove all but one of the beans; or " + + "implement the SchedulingConfigurer interface and call " + + "ScheduledTaskRegistrar#setScheduler explicitly within the " + + "configureTasks() callback. Found the following beans: " + schedulers.keySet()); + } + } + + this.registrar.afterPropertiesSet(); + } + + @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; @@ -254,44 +307,6 @@ public class ScheduledAnnotationBeanPostProcessor } } - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - if (event.getApplicationContext() != this.applicationContext) { - return; - } - - if (this.scheduler != null) { - this.registrar.setScheduler(this.scheduler); - } - - Map configurers = - this.applicationContext.getBeansOfType(SchedulingConfigurer.class); - for (SchedulingConfigurer configurer : configurers.values()) { - configurer.configureTasks(this.registrar); - } - - if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) { - Map schedulers = new HashMap(); - schedulers.putAll(this.applicationContext.getBeansOfType(TaskScheduler.class)); - schedulers.putAll(this.applicationContext.getBeansOfType(ScheduledExecutorService.class)); - if (schedulers.size() == 0) { - // do nothing -> fall back to default scheduler - } - else if (schedulers.size() == 1) { - this.registrar.setScheduler(schedulers.values().iterator().next()); - } - else if (schedulers.size() >= 2){ - throw new IllegalStateException( - "More than one TaskScheduler and/or ScheduledExecutorService " + - "exist within the context. Remove all but one of the beans; or " + - "implement the SchedulingConfigurer interface and call " + - "ScheduledTaskRegistrar#setScheduler explicitly within the " + - "configureTasks() callback. Found the following beans: " + schedulers.keySet()); - } - } - - this.registrar.afterPropertiesSet(); - } @Override public void destroy() { diff --git a/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java b/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java index 187f1fb5de6..fb4f49ebff4 100644 --- a/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java +++ b/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java @@ -22,14 +22,14 @@ import java.util.concurrent.atomic.AtomicInteger; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.AnnotationConfigUtils; -import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.jms.config.DefaultJmsHandlerMethodFactory; @@ -39,6 +39,7 @@ import org.springframework.jms.config.JmsListenerEndpointRegistrar; import org.springframework.jms.config.JmsListenerEndpointRegistry; import org.springframework.jms.config.MethodJmsListenerEndpoint; import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; +import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -60,6 +61,7 @@ import org.springframework.util.StringUtils; * {@link EnableJms} Javadoc for complete usage details. * * @author Stephane Nicoll + * @author Juergen Hoeller * @since 4.1 * @see JmsListener * @see EnableJms @@ -69,11 +71,11 @@ import org.springframework.util.StringUtils; * @see org.springframework.jms.config.AbstractJmsListenerEndpoint * @see MethodJmsListenerEndpoint */ -public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered, - ApplicationContextAware, ApplicationListener { +public class JmsListenerAnnotationBeanPostProcessor + implements BeanPostProcessor, Ordered, BeanFactoryAware, SmartInitializingSingleton { /** - * The bean name of the default {@link JmsListenerContainerFactory} + * The bean name of the default {@link JmsListenerContainerFactory}. */ static final String DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME = "jmsListenerContainerFactory"; @@ -82,9 +84,9 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME; - private final JmsHandlerMethodFactoryAdapter jmsHandlerMethodFactory = new JmsHandlerMethodFactoryAdapter(); + private BeanFactory beanFactory; - private ApplicationContext applicationContext; + private final JmsHandlerMethodFactoryAdapter jmsHandlerMethodFactory = new JmsHandlerMethodFactoryAdapter(); private final JmsListenerEndpointRegistrar registrar = new JmsListenerEndpointRegistrar(); @@ -124,9 +126,50 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor this.jmsHandlerMethodFactory.setJmsHandlerMethodFactory(jmsHandlerMethodFactory); } + /** + * Making a {@link BeanFactory} available is optional; if not set, + * {@link JmsListenerConfigurer} beans won't get autodetected and an + * {@link #setEndpointRegistry endpoint registry} has to be explicitly configured. + */ @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + + @Override + public void afterSingletonsInstantiated() { + this.registrar.setBeanFactory(this.beanFactory); + + if (this.beanFactory instanceof ListableBeanFactory) { + Map instances = + ((ListableBeanFactory) this.beanFactory).getBeansOfType(JmsListenerConfigurer.class); + for (JmsListenerConfigurer configurer : instances.values()) { + configurer.configureJmsListeners(this.registrar); + } + } + + if (this.registrar.getEndpointRegistry() == null) { + if (this.endpointRegistry == null) { + Assert.state(this.beanFactory != null, "BeanFactory must be set to find endpoint registry by bean name"); + this.endpointRegistry = this.beanFactory.getBean( + AnnotationConfigUtils.JMS_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME, JmsListenerEndpointRegistry.class); + } + this.registrar.setEndpointRegistry(this.endpointRegistry); + } + + if (this.containerFactoryBeanName != null) { + this.registrar.setContainerFactoryBeanName(this.containerFactoryBeanName); + } + + // Set the custom handler method factory once resolved by the configurer + JmsHandlerMethodFactory handlerMethodFactory = this.registrar.getJmsHandlerMethodFactory(); + if (handlerMethodFactory != null) { + this.jmsHandlerMethodFactory.setJmsHandlerMethodFactory(handlerMethodFactory); + } + + // Actually register all listeners + this.registrar.afterPropertiesSet(); } @@ -189,8 +232,9 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor JmsListenerContainerFactory factory = null; String containerFactoryBeanName = jmsListener.containerFactory(); if (StringUtils.hasText(containerFactoryBeanName)) { + Assert.state(this.beanFactory != null, "BeanFactory must be set to obtain container factory by bean name"); try { - factory = this.applicationContext.getBean(containerFactoryBeanName, JmsListenerContainerFactory.class); + factory = this.beanFactory.getBean(containerFactoryBeanName, JmsListenerContainerFactory.class); } catch (NoSuchBeanDefinitionException ex) { throw new BeanInitializationException("Could not register jms listener endpoint on [" + @@ -199,49 +243,7 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor } } - registrar.registerEndpoint(endpoint, factory); - - } - - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - if (event.getApplicationContext() != this.applicationContext) { - return; - } - - Map instances = - this.applicationContext.getBeansOfType(JmsListenerConfigurer.class); - for (JmsListenerConfigurer configurer : instances.values()) { - configurer.configureJmsListeners(registrar); - } - - this.registrar.setApplicationContext(this.applicationContext); - - if (this.registrar.getEndpointRegistry() == null) { - if (this.endpointRegistry == null) { - this.endpointRegistry = this.applicationContext.getBean( - AnnotationConfigUtils.JMS_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME, JmsListenerEndpointRegistry.class); - } - this.registrar.setEndpointRegistry(this.endpointRegistry); - } - - if (this.containerFactoryBeanName != null) { - this.registrar.setContainerFactoryBeanName(this.containerFactoryBeanName); - } - - // Set the custom handler method factory once resolved by the configurer - JmsHandlerMethodFactory handlerMethodFactory = registrar.getJmsHandlerMethodFactory(); - if (handlerMethodFactory != null) { - this.jmsHandlerMethodFactory.setJmsHandlerMethodFactory(handlerMethodFactory); - } - - // Create all the listeners and starts them - try { - this.registrar.afterPropertiesSet(); - } - catch (Exception ex) { - throw new BeanInitializationException("Failed to initialize JmsListenerEndpointRegistrar", ex); - } + this.registrar.registerEndpoint(endpoint, factory); } private String getEndpointId(JmsListener jmsListener) { @@ -282,7 +284,7 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor private JmsHandlerMethodFactory createDefaultJmsHandlerMethodFactory() { DefaultJmsHandlerMethodFactory defaultFactory = new DefaultJmsHandlerMethodFactory(); - defaultFactory.setApplicationContext(applicationContext); + defaultFactory.setBeanFactory(beanFactory); defaultFactory.afterPropertiesSet(); return defaultFactory; } diff --git a/spring-jms/src/main/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactory.java b/spring-jms/src/main/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactory.java index 5b4f165c5f5..4f0f9d0f20b 100644 --- a/spring-jms/src/main/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactory.java +++ b/spring-jms/src/main/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactory.java @@ -20,11 +20,10 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.convert.ConversionService; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.messaging.converter.GenericMessageConverter; @@ -36,8 +35,6 @@ import org.springframework.messaging.handler.annotation.support.PayloadArgumentR import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite; import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.validation.Errors; import org.springframework.validation.Validator; @@ -57,15 +54,13 @@ import org.springframework.validation.Validator; * can be converted * * @author Stephane Nicoll + * @author Juergen Hoeller * @since 4.1 - * @see #setCustomArgumentResolvers(java.util.List) - * @see #setValidator(Validator) - * @see #setConversionService(ConversionService) + * @see #setConversionService + * @see #setValidator + * @see #setCustomArgumentResolvers */ -public class DefaultJmsHandlerMethodFactory - implements JmsHandlerMethodFactory, InitializingBean, ApplicationContextAware { - - private ApplicationContext applicationContext; +public class DefaultJmsHandlerMethodFactory implements JmsHandlerMethodFactory, BeanFactoryAware, InitializingBean { private ConversionService conversionService = new DefaultFormattingConversionService(); @@ -73,22 +68,17 @@ public class DefaultJmsHandlerMethodFactory private Validator validator = new NoOpValidator(); - private List customArgumentResolvers - = new ArrayList(); + private List customArgumentResolvers; - private HandlerMethodArgumentResolverComposite argumentResolvers - = new HandlerMethodArgumentResolverComposite(); + private final HandlerMethodArgumentResolverComposite argumentResolvers = + new HandlerMethodArgumentResolverComposite(); + private BeanFactory beanFactory; - @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } /** * Set the {@link ConversionService} to use to convert the original * message payload or headers. - * * @see HeaderMethodArgumentResolver * @see GenericMessageConverter */ @@ -96,24 +86,15 @@ public class DefaultJmsHandlerMethodFactory this.conversionService = conversionService; } - protected ConversionService getConversionService() { - return conversionService; - } - /** * Set the {@link MessageConverter} to use. By default a {@link GenericMessageConverter} * is used. - * * @see GenericMessageConverter */ public void setMessageConverter(MessageConverter messageConverter) { this.messageConverter = messageConverter; } - protected MessageConverter getMessageConverter() { - return messageConverter; - } - /** * Set the Validator instance used for validating @Payload arguments * @see org.springframework.validation.annotation.Validated @@ -123,27 +104,15 @@ public class DefaultJmsHandlerMethodFactory this.validator = validator; } - /** - * The configured Validator instance - */ - public Validator getValidator() { - return validator; - } - /** * Set the list of custom {@code HandlerMethodArgumentResolver}s that will be used * after resolvers for supported argument type. - * @param customArgumentResolvers the list of resolvers; never {@code null}. + * @param customArgumentResolvers the list of resolvers (never {@code null}) */ public void setCustomArgumentResolvers(List customArgumentResolvers) { - Assert.notNull(customArgumentResolvers, "The 'customArgumentResolvers' cannot be null."); this.customArgumentResolvers = customArgumentResolvers; } - public List getCustomArgumentResolvers() { - return customArgumentResolvers; - } - /** * Configure the complete list of supported argument types effectively overriding * the ones configured by default. This is an advanced option. For most use cases @@ -157,20 +126,26 @@ public class DefaultJmsHandlerMethodFactory this.argumentResolvers.addResolvers(argumentResolvers); } - public List getArgumentResolvers() { - return this.argumentResolvers.getResolvers(); + /** + * A {@link BeanFactory} only needs to be available for placeholder resolution + * in handler method arguments; it's optional otherwise. + */ + @Override + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; } @Override public void afterPropertiesSet() { - if (messageConverter == null) { - messageConverter = new GenericMessageConverter(getConversionService()); + if (this.messageConverter == null) { + this.messageConverter = new GenericMessageConverter(this.conversionService); } if (this.argumentResolvers.getResolvers().isEmpty()) { this.argumentResolvers.addResolvers(initArgumentResolvers()); } } + @Override public InvocableHandlerMethod createInvocableHandlerMethod(Object bean, Method method) { InvocableHandlerMethod handlerMethod = new InvocableHandlerMethod(bean, method); @@ -179,27 +154,28 @@ public class DefaultJmsHandlerMethodFactory } protected List initArgumentResolvers() { - ConfigurableBeanFactory beanFactory = - (ClassUtils.isAssignableValue(ConfigurableApplicationContext.class, applicationContext)) ? - ((ConfigurableApplicationContext) applicationContext).getBeanFactory() : null; - List resolvers = new ArrayList(); + ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory ? + (ConfigurableBeanFactory) this.beanFactory : null); // Annotation-based argument resolution - resolvers.add(new HeaderMethodArgumentResolver(getConversionService(), beanFactory)); + resolvers.add(new HeaderMethodArgumentResolver(this.conversionService, cbf)); resolvers.add(new HeadersMethodArgumentResolver()); // Type-based argument resolution resolvers.add(new MessageMethodArgumentResolver()); - resolvers.addAll(getCustomArgumentResolvers()); - resolvers.add(new PayloadArgumentResolver(getMessageConverter(), getValidator())); + if (this.customArgumentResolvers != null) { + resolvers.addAll(this.customArgumentResolvers); + } + resolvers.add(new PayloadArgumentResolver(this.messageConverter, this.validator)); return resolvers; } private static final class NoOpValidator implements Validator { + @Override public boolean supports(Class clazz) { return false; diff --git a/spring-jms/src/main/java/org/springframework/jms/config/JmsListenerEndpointRegistrar.java b/spring-jms/src/main/java/org/springframework/jms/config/JmsListenerEndpointRegistrar.java index 75f24e02dd2..df1d0279135 100644 --- a/spring-jms/src/main/java/org/springframework/jms/config/JmsListenerEndpointRegistrar.java +++ b/spring-jms/src/main/java/org/springframework/jms/config/JmsListenerEndpointRegistrar.java @@ -19,9 +19,9 @@ package org.springframework.jms.config; import java.util.ArrayList; import java.util.List; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.util.Assert; /** @@ -29,24 +29,26 @@ import org.springframework.util.Assert; * a {@link JmsListenerEndpointRegistry}. * * @author Stephane Nicoll + * @author Juergen Hoeller * @since 4.1 * @see org.springframework.jms.annotation.JmsListenerConfigurer */ -public class JmsListenerEndpointRegistrar implements ApplicationContextAware, InitializingBean { +public class JmsListenerEndpointRegistrar implements BeanFactoryAware, InitializingBean { private JmsListenerEndpointRegistry endpointRegistry; - private String containerFactoryBeanName; + private JmsHandlerMethodFactory jmsHandlerMethodFactory; private JmsListenerContainerFactory containerFactory; - private JmsHandlerMethodFactory jmsHandlerMethodFactory; + private String containerFactoryBeanName; - private ApplicationContext applicationContext; + private BeanFactory beanFactory; private final List endpointDescriptors = new ArrayList(); + /** * Set the {@link JmsListenerEndpointRegistry} instance to use. */ @@ -59,27 +61,7 @@ public class JmsListenerEndpointRegistrar implements ApplicationContextAware, In * registrar, may be {@code null}. */ public JmsListenerEndpointRegistry getEndpointRegistry() { - return endpointRegistry; - } - - /** - * Set the bean name of the {@link JmsListenerContainerFactory} to use in - * case a {@link JmsListenerEndpoint} is registered with a {@code null} - * container factory. Alternatively, the container factory instance can - * be registered directly, see {@link #setContainerFactory(JmsListenerContainerFactory)} - */ - public void setContainerFactoryBeanName(String containerFactoryBeanName) { - this.containerFactoryBeanName = containerFactoryBeanName; - } - - /** - * Set the {@link JmsListenerContainerFactory} to use in case a {@link JmsListenerEndpoint} - * is registered with a {@code null} container factory. - *

Alternatively, the bean name of the {@link JmsListenerContainerFactory} to use - * can be specified for a lazy lookup, see {@link #setContainerFactoryBeanName}. - */ - public void setContainerFactory(JmsListenerContainerFactory containerFactory) { - this.containerFactory = containerFactory; + return this.endpointRegistry; } /** @@ -98,12 +80,69 @@ public class JmsListenerEndpointRegistrar implements ApplicationContextAware, In * Return the custom {@link JmsHandlerMethodFactory} to use, if any. */ public JmsHandlerMethodFactory getJmsHandlerMethodFactory() { - return jmsHandlerMethodFactory; + return this.jmsHandlerMethodFactory; } + /** + * Set the {@link JmsListenerContainerFactory} to use in case a {@link JmsListenerEndpoint} + * is registered with a {@code null} container factory. + *

Alternatively, the bean name of the {@link JmsListenerContainerFactory} to use + * can be specified for a lazy lookup, see {@link #setContainerFactoryBeanName}. + */ + public void setContainerFactory(JmsListenerContainerFactory containerFactory) { + this.containerFactory = containerFactory; + } + + /** + * Set the bean name of the {@link JmsListenerContainerFactory} to use in case + * a {@link JmsListenerEndpoint} is registered with a {@code null} container factory. + * Alternatively, the container factory instance can be registered directly: + * see {@link #setContainerFactory(JmsListenerContainerFactory)}. + * @see #setBeanFactory + */ + public void setContainerFactoryBeanName(String containerFactoryBeanName) { + this.containerFactoryBeanName = containerFactoryBeanName; + } + + /** + * A {@link BeanFactory} only needs to be available in conjunction with + * {@link #setContainerFactoryBeanName}. + */ @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + + @Override + public void afterPropertiesSet() { + registerAllEndpoints(); + } + + protected void registerAllEndpoints() { + for (JmsListenerEndpointDescriptor descriptor : this.endpointDescriptors) { + this.endpointRegistry.registerListenerContainer(descriptor.endpoint, resolveContainerFactory(descriptor)); + } + } + + private JmsListenerContainerFactory resolveContainerFactory(JmsListenerEndpointDescriptor descriptor) { + if (descriptor.containerFactory != null) { + return descriptor.containerFactory; + } + else if (this.containerFactory != null) { + return this.containerFactory; + } + else if (this.containerFactoryBeanName != null) { + Assert.state(this.beanFactory != null, "BeanFactory must be set to obtain container factory by bean name"); + this.containerFactory = this.beanFactory.getBean( + this.containerFactoryBeanName, JmsListenerContainerFactory.class); + return this.containerFactory; // Consider changing this if live change of the factory is required + } + else { + throw new IllegalStateException("Could not resolve the " + + JmsListenerContainerFactory.class.getSimpleName() + " to use for [" + + descriptor.endpoint + "] no factory was given and no default is set."); + } } /** @@ -129,38 +168,6 @@ public class JmsListenerEndpointRegistrar implements ApplicationContextAware, In registerEndpoint(endpoint, null); } - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(applicationContext, "ApplicationContext must not be null"); - startAllEndpoints(); - } - - protected void startAllEndpoints() throws Exception { - for (JmsListenerEndpointDescriptor descriptor : endpointDescriptors) { - endpointRegistry.registerListenerContainer( - descriptor.endpoint, resolveContainerFactory(descriptor)); - } - } - - private JmsListenerContainerFactory resolveContainerFactory(JmsListenerEndpointDescriptor descriptor) { - if (descriptor.containerFactory != null) { - return descriptor.containerFactory; - } - else if (this.containerFactory != null) { - return this.containerFactory; - } - else if (this.containerFactoryBeanName != null) { - this.containerFactory = this.applicationContext.getBean( - this.containerFactoryBeanName, JmsListenerContainerFactory.class); - return this.containerFactory; // Consider changing this if live change of the factory is required - } - else { - throw new IllegalStateException("Could not resolve the " + - JmsListenerContainerFactory.class.getSimpleName() + " to use for [" + - descriptor.endpoint + "] no factory was given and no default is set."); - } - } - private static class JmsListenerEndpointDescriptor { diff --git a/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java b/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java index ec9a3565aa1..fe96e08b826 100644 --- a/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java @@ -40,6 +40,7 @@ import static org.junit.Assert.*; /** * @author Stephane Nicoll + * @author Juergen Hoeller */ public class JmsListenerAnnotationBeanPostProcessorTests { @@ -62,9 +63,7 @@ public class JmsListenerAnnotationBeanPostProcessorTests { 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()); } diff --git a/spring-jms/src/test/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactoryTests.java b/spring-jms/src/test/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactoryTests.java index 0e9cd9cdcbb..5ea4d98bd7b 100644 --- a/spring-jms/src/test/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactoryTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/config/DefaultJmsHandlerMethodFactoryTests.java @@ -16,8 +16,6 @@ package org.springframework.jms.config; -import static org.junit.Assert.*; - import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -31,7 +29,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TestName; -import org.springframework.context.support.StaticApplicationContext; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.core.MethodParameter; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.GenericConversionService; @@ -44,8 +42,9 @@ import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.ReflectionUtils; +import static org.junit.Assert.*; + /** - * * @author Stephane Nicoll */ public class DefaultJmsHandlerMethodFactoryTests { @@ -160,15 +159,13 @@ public class DefaultJmsHandlerMethodFactoryTests { private DefaultJmsHandlerMethodFactory createInstance() { DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory(); - factory.setApplicationContext(new StaticApplicationContext()); + factory.setBeanFactory(new StaticListableBeanFactory()); return factory; } private Method getListenerMethod(String methodName, Class... parameterTypes) { - Method method = ReflectionUtils.findMethod(SampleBean.class, - methodName, parameterTypes); - assertNotNull("no method found with name " + methodName - + " and parameters " + Arrays.toString(parameterTypes)); + Method method = ReflectionUtils.findMethod(SampleBean.class, methodName, parameterTypes); + assertNotNull("no method found with name " + methodName + " and parameters " + Arrays.toString(parameterTypes)); return method; } @@ -187,6 +184,7 @@ public class DefaultJmsHandlerMethodFactoryTests { } } + static class CustomHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override diff --git a/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerContainerFactoryIntegrationTests.java b/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerContainerFactoryIntegrationTests.java index 77a6585ec06..198b37af15d 100644 --- a/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerContainerFactoryIntegrationTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerContainerFactoryIntegrationTests.java @@ -16,14 +16,10 @@ package org.springframework.jms.config; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.Map; - import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; @@ -33,7 +29,7 @@ import javax.jms.TextMessage; import org.junit.Before; import org.junit.Test; -import org.springframework.context.support.StaticApplicationContext; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.jms.StubTextMessage; import org.springframework.jms.listener.DefaultMessageListenerContainer; import org.springframework.jms.listener.SessionAwareMessageListener; @@ -42,8 +38,10 @@ import org.springframework.jms.support.converter.MessageConverter; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.util.ReflectionUtils; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + /** - * * @author Stephane Nicoll */ public class JmsListenerContainerFactoryIntegrationTests { @@ -54,6 +52,7 @@ public class JmsListenerContainerFactoryIntegrationTests { private final JmsEndpointSampleBean sample = new JmsEndpointSampleBean(); + @Before public void setup() { initializeFactory(factory); @@ -70,16 +69,6 @@ public class JmsListenerContainerFactoryIntegrationTests { assertListenerMethodInvocation("expectFooBarUpperCase"); } - static class JmsEndpointSampleBean { - - private final Map invocations = new HashMap(); - - public void expectFooBarUpperCase(@Payload String msg) { - invocations.put("expectFooBarUpperCase", true); - assertEquals("Unexpected payload message", "FOO-BAR", msg); - } - } - @SuppressWarnings("unchecked") private void invokeListener(JmsListenerEndpoint endpoint, Message message) throws JMSException { DefaultMessageListenerContainer messageListenerContainer = @@ -112,21 +101,31 @@ public class JmsListenerContainerFactoryIntegrationTests { } private Method getListenerMethod(String methodName, Class... parameterTypes) { - Method method = ReflectionUtils.findMethod(JmsEndpointSampleBean.class, - methodName, parameterTypes); - assertNotNull("no method found with name " + methodName - + " and parameters " + Arrays.toString(parameterTypes)); + Method method = ReflectionUtils.findMethod(JmsEndpointSampleBean.class, methodName, parameterTypes); + assertNotNull("no method found with name " + methodName + " and parameters " + Arrays.toString(parameterTypes)); return method; } private void initializeFactory(DefaultJmsHandlerMethodFactory factory) { - factory.setApplicationContext(new StaticApplicationContext()); + factory.setBeanFactory(new StaticListableBeanFactory()); factory.afterPropertiesSet(); } + static class JmsEndpointSampleBean { + + private final Map invocations = new HashMap(); + + public void expectFooBarUpperCase(@Payload String msg) { + invocations.put("expectFooBarUpperCase", true); + assertEquals("Unexpected payload message", "FOO-BAR", msg); + } + } + + private static class UpperCaseMessageConverter implements MessageConverter { + @Override public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { return new StubTextMessage(object.toString().toUpperCase()); @@ -138,6 +137,5 @@ public class JmsListenerContainerFactoryIntegrationTests { return content.toUpperCase(); } } + } - - diff --git a/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerEndpointRegistrarTests.java b/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerEndpointRegistrarTests.java index aae03c2d106..b0fde624002 100644 --- a/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerEndpointRegistrarTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/config/JmsListenerEndpointRegistrarTests.java @@ -16,17 +16,16 @@ package org.springframework.jms.config; -import static org.junit.Assert.*; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.springframework.context.support.StaticApplicationContext; +import org.springframework.beans.factory.support.StaticListableBeanFactory; + +import static org.junit.Assert.*; /** - * * @author Stephane Nicoll */ public class JmsListenerEndpointRegistrarTests { @@ -40,10 +39,11 @@ public class JmsListenerEndpointRegistrarTests { private final JmsListenerContainerTestFactory containerFactory = new JmsListenerContainerTestFactory(); + @Before public void setup() { registrar.setEndpointRegistry(registry); - registrar.setApplicationContext(new StaticApplicationContext()); + registrar.setBeanFactory(new StaticListableBeanFactory()); } @Test diff --git a/spring-jms/src/test/java/org/springframework/jms/config/MethodJmsListenerEndpointTests.java b/spring-jms/src/test/java/org/springframework/jms/config/MethodJmsListenerEndpointTests.java index e4525361e82..cc73655f76f 100644 --- a/spring-jms/src/test/java/org/springframework/jms/config/MethodJmsListenerEndpointTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/config/MethodJmsListenerEndpointTests.java @@ -16,16 +16,11 @@ package org.springframework.jms.config; -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.*; - import java.io.Serializable; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.Map; - import javax.jms.Destination; import javax.jms.InvalidDestinationException; import javax.jms.JMSException; @@ -41,16 +36,16 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TestName; -import org.springframework.context.support.StaticApplicationContext; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.jms.StubTextMessage; import org.springframework.jms.listener.DefaultMessageListenerContainer; import org.springframework.jms.listener.MessageListenerContainer; import org.springframework.jms.listener.SimpleMessageListenerContainer; -import org.springframework.jms.listener.adapter.ReplyFailureException; import org.springframework.jms.listener.adapter.ListenerExecutionFailedException; import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter; -import org.springframework.jms.support.JmsMessageHeaderAccessor; +import org.springframework.jms.listener.adapter.ReplyFailureException; import org.springframework.jms.support.JmsHeaders; +import org.springframework.jms.support.JmsMessageHeaderAccessor; import org.springframework.jms.support.destination.DestinationResolver; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; @@ -65,8 +60,12 @@ import org.springframework.validation.Errors; import org.springframework.validation.Validator; import org.springframework.validation.annotation.Validated; +import static org.junit.Assert.*; +import static org.mockito.BDDMockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + /** - * * @author Stephane Nicoll */ public class MethodJmsListenerEndpointTests { @@ -83,6 +82,7 @@ public class MethodJmsListenerEndpointTests { private final JmsEndpointSampleBean sample = new JmsEndpointSampleBean(); + @Before public void setup() { initializeFactory(factory); @@ -375,10 +375,8 @@ public class MethodJmsListenerEndpointTests { } private Method getListenerMethod(String methodName, Class... parameterTypes) { - Method method = ReflectionUtils.findMethod(JmsEndpointSampleBean.class, - methodName, parameterTypes); - assertNotNull("no method found with name " + methodName - + " and parameters " + Arrays.toString(parameterTypes)); + Method method = ReflectionUtils.findMethod(JmsEndpointSampleBean.class, methodName, parameterTypes); + assertNotNull("no method found with name " + methodName + " and parameters " + Arrays.toString(parameterTypes)); return method; } @@ -395,12 +393,11 @@ public class MethodJmsListenerEndpointTests { } private void initializeFactory(DefaultJmsHandlerMethodFactory factory) { - factory.setApplicationContext(new StaticApplicationContext()); + factory.setBeanFactory(new StaticListableBeanFactory()); factory.afterPropertiesSet(); } private Validator testValidator(final String invalidValue) { - return new Validator() { @Override public boolean supports(Class clazz) { @@ -520,11 +517,11 @@ public class MethodJmsListenerEndpointTests { } + @SuppressWarnings("serial") static class MyBean implements Serializable { private String name; } - } diff --git a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java index 581cc68b747..18414559011 100644 --- a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessagingMessageListenerAdapterTests.java @@ -25,7 +25,7 @@ import javax.jms.TextMessage; import org.junit.Before; import org.junit.Test; -import org.springframework.context.support.StaticApplicationContext; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.jms.StubTextMessage; import org.springframework.jms.config.DefaultJmsHandlerMethodFactory; import org.springframework.jms.support.JmsHeaders; @@ -38,7 +38,6 @@ import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; /** - * * @author Stephane Nicoll */ public class MessagingMessageListenerAdapterTests { @@ -124,7 +123,7 @@ public class MessagingMessageListenerAdapterTests { } private void initializeFactory(DefaultJmsHandlerMethodFactory factory) { - factory.setApplicationContext(new StaticApplicationContext()); + factory.setBeanFactory(new StaticListableBeanFactory()); factory.afterPropertiesSet(); }