Fix Auto-Startup for @JmsListener
Ignore container's auto-startup once the context is refreshed. Issue: SPR-14015
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2015 the original author or authors.
|
* Copyright 2002-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,10 +26,15 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.BeanInitializationException;
|
import org.springframework.beans.factory.BeanInitializationException;
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
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.context.ApplicationListener;
|
||||||
import org.springframework.context.SmartLifecycle;
|
import org.springframework.context.SmartLifecycle;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
import org.springframework.jms.listener.MessageListenerContainer;
|
import org.springframework.jms.listener.MessageListenerContainer;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -53,7 +58,8 @@ import org.springframework.util.Assert;
|
|||||||
* @see MessageListenerContainer
|
* @see MessageListenerContainer
|
||||||
* @see JmsListenerContainerFactory
|
* @see JmsListenerContainerFactory
|
||||||
*/
|
*/
|
||||||
public class JmsListenerEndpointRegistry implements DisposableBean, SmartLifecycle {
|
public class JmsListenerEndpointRegistry implements DisposableBean, SmartLifecycle,
|
||||||
|
ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
@@ -62,6 +68,15 @@ public class JmsListenerEndpointRegistry implements DisposableBean, SmartLifecyc
|
|||||||
|
|
||||||
private int phase = Integer.MAX_VALUE;
|
private int phase = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private boolean contextRefreshed;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@link MessageListenerContainer} with the specified id or
|
* Return the {@link MessageListenerContainer} with the specified id or
|
||||||
@@ -181,6 +196,13 @@ public class JmsListenerEndpointRegistry implements DisposableBean, SmartLifecyc
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||||
|
if (event.getApplicationContext().equals(this.applicationContext)) {
|
||||||
|
this.contextRefreshed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delegating implementation of SmartLifecycle
|
// Delegating implementation of SmartLifecycle
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -228,11 +250,11 @@ public class JmsListenerEndpointRegistry implements DisposableBean, SmartLifecyc
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the specified {@link MessageListenerContainer} if it should be started
|
* Start the specified {@link MessageListenerContainer} if it should be started
|
||||||
* on startup.
|
* on startup or when start is called explicitly after startup.
|
||||||
* @see MessageListenerContainer#isAutoStartup()
|
* @see MessageListenerContainer#isAutoStartup()
|
||||||
*/
|
*/
|
||||||
private static void startIfNecessary(MessageListenerContainer listenerContainer) {
|
private void startIfNecessary(MessageListenerContainer listenerContainer) {
|
||||||
if (listenerContainer.isAutoStartup()) {
|
if (this.contextRefreshed || listenerContainer.isAutoStartup()) {
|
||||||
listenerContainer.start();
|
listenerContainer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,31 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
|
|||||||
testDefaultContainerFactoryConfiguration(context);
|
testDefaultContainerFactoryConfiguration(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containerAreStartedByDefault() {
|
||||||
|
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
EnableJmsDefaultContainerFactoryConfig.class, DefaultBean.class);
|
||||||
|
JmsListenerContainerTestFactory factory =
|
||||||
|
context.getBean(JmsListenerContainerTestFactory.class);
|
||||||
|
MessageListenerTestContainer container = factory.getListenerContainers().get(0);
|
||||||
|
assertTrue(container.isAutoStartup());
|
||||||
|
assertTrue(container.isStarted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containerCanBeStarterViaTheRegistry() {
|
||||||
|
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
EnableJmsAutoStartupFalseConfig.class, DefaultBean.class);
|
||||||
|
JmsListenerContainerTestFactory factory =
|
||||||
|
context.getBean(JmsListenerContainerTestFactory.class);
|
||||||
|
MessageListenerTestContainer container = factory.getListenerContainers().get(0);
|
||||||
|
assertFalse(container.isAutoStartup());
|
||||||
|
assertFalse(container.isStarted());
|
||||||
|
JmsListenerEndpointRegistry registry = context.getBean(JmsListenerEndpointRegistry.class);
|
||||||
|
registry.start();
|
||||||
|
assertTrue(container.isStarted());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Test
|
@Test
|
||||||
public void jmsHandlerMethodFactoryConfiguration() throws JMSException {
|
public void jmsHandlerMethodFactoryConfiguration() throws JMSException {
|
||||||
@@ -314,6 +339,23 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableJms
|
||||||
|
static class EnableJmsAutoStartupFalseConfig implements JmsListenerConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
|
||||||
|
registrar.setContainerFactory(simpleFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JmsListenerContainerTestFactory simpleFactory() {
|
||||||
|
JmsListenerContainerTestFactory factory = new JmsListenerContainerTestFactory();
|
||||||
|
factory.setAutoStartup(false);
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Lazy
|
@Lazy
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2015 the original author or authors.
|
* Copyright 2002-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,9 +26,15 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class JmsListenerContainerTestFactory implements JmsListenerContainerFactory<MessageListenerTestContainer> {
|
public class JmsListenerContainerTestFactory implements JmsListenerContainerFactory<MessageListenerTestContainer> {
|
||||||
|
|
||||||
|
private boolean autoStartup = true;
|
||||||
|
|
||||||
private final Map<String, MessageListenerTestContainer> listenerContainers =
|
private final Map<String, MessageListenerTestContainer> listenerContainers =
|
||||||
new LinkedHashMap<>();
|
new LinkedHashMap<>();
|
||||||
|
|
||||||
|
public void setAutoStartup(boolean autoStartup) {
|
||||||
|
this.autoStartup = autoStartup;
|
||||||
|
}
|
||||||
|
|
||||||
public List<MessageListenerTestContainer> getListenerContainers() {
|
public List<MessageListenerTestContainer> getListenerContainers() {
|
||||||
return new ArrayList<>(this.listenerContainers.values());
|
return new ArrayList<>(this.listenerContainers.values());
|
||||||
}
|
}
|
||||||
@@ -40,6 +46,7 @@ public class JmsListenerContainerTestFactory implements JmsListenerContainerFact
|
|||||||
@Override
|
@Override
|
||||||
public MessageListenerTestContainer createListenerContainer(JmsListenerEndpoint endpoint) {
|
public MessageListenerTestContainer createListenerContainer(JmsListenerEndpoint endpoint) {
|
||||||
MessageListenerTestContainer container = new MessageListenerTestContainer(endpoint);
|
MessageListenerTestContainer container = new MessageListenerTestContainer(endpoint);
|
||||||
|
container.setAutoStartup(this.autoStartup);
|
||||||
this.listenerContainers.put(endpoint.getId(), container);
|
this.listenerContainers.put(endpoint.getId(), container);
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2015 the original author or authors.
|
* Copyright 2002-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -31,6 +31,8 @@ public class MessageListenerTestContainer
|
|||||||
|
|
||||||
private final JmsListenerEndpoint endpoint;
|
private final JmsListenerEndpoint endpoint;
|
||||||
|
|
||||||
|
private boolean autoStartup = true;
|
||||||
|
|
||||||
private boolean startInvoked;
|
private boolean startInvoked;
|
||||||
|
|
||||||
private boolean initializationInvoked;
|
private boolean initializationInvoked;
|
||||||
@@ -43,6 +45,10 @@ public class MessageListenerTestContainer
|
|||||||
this.endpoint = endpoint;
|
this.endpoint = endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAutoStartup(boolean autoStartup) {
|
||||||
|
this.autoStartup = autoStartup;
|
||||||
|
}
|
||||||
|
|
||||||
public JmsListenerEndpoint getEndpoint() {
|
public JmsListenerEndpoint getEndpoint() {
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
@@ -86,7 +92,7 @@ public class MessageListenerTestContainer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAutoStartup() {
|
public boolean isAutoStartup() {
|
||||||
return true;
|
return this.autoStartup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user