Browse Source

Fix Auto-Startup for @JmsListener

Ignore container's auto-startup once the context is refreshed.

Issue: SPR-14015
pull/1004/merge
Stephane Nicoll 10 years ago
parent
commit
996c1cc0a6
  1. 32
      spring-jms/src/main/java/org/springframework/jms/config/JmsListenerEndpointRegistry.java
  2. 42
      spring-jms/src/test/java/org/springframework/jms/annotation/EnableJmsTests.java
  3. 9
      spring-jms/src/test/java/org/springframework/jms/config/JmsListenerContainerTestFactory.java
  4. 10
      spring-jms/src/test/java/org/springframework/jms/config/MessageListenerTestContainer.java

32
spring-jms/src/main/java/org/springframework/jms/config/JmsListenerEndpointRegistry.java

@ -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();
} }
} }

42
spring-jms/src/test/java/org/springframework/jms/annotation/EnableJmsTests.java

@ -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

9
spring-jms/src/test/java/org/springframework/jms/config/JmsListenerContainerTestFactory.java

@ -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;
} }

10
spring-jms/src/test/java/org/springframework/jms/config/MessageListenerTestContainer.java

@ -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

Loading…
Cancel
Save