1

I am trying to start/stop manually JMS listeners in my Spring Boot App. I am currently using the following configuration to my container factory:

@EnableJms
public class ConfigJms {
...
    @Bean(name = "queueContainerFactory")
    public JmsListenerContainerFactory<?> queueContainerFactory(ConnectionFactory cf) {

        ActiveMQConnectionFactory amqCf = (ActiveMQConnectionFactory) cf;
        amqCf.setTrustAllPackages(true);
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(amqCf);
        **factory.setAutoStartup(false);** 
        return factory;
    }
...
}

After testing factory.setAutoStartup(false); I am quite confused because even indicating to do not start any listener for this factory container, the listeners are already registered and started when the context starts.

I tested this situation by using a jmsListenerEndpointRegistry.

jmsListenerEndpointRegistry.isAutoStartup() is true and jmsListenerEndpointRegistry. isRunning () is true before execute jmsListenerEndpointRegistry.start();

Is it necessary to configure anything else? Maybe I am omitting to override some auto-configuration.

EDIT 1: Invalid status of JmsListenerEndpointRegistry listeners

I detected a couple of inconsistences in my beans:

jmsListenerEndpointRegistry.getListenerContainerIds().size() is always 0. jmsListenerEndpointRegistry.isAutoStartup() is just a return true method.

Even if I register a couple of listeners with annotations like this:

@JmsListener(containerFactory="queueContainerFactory", destination = "${dest}")

jmsListenerEndpointRegistry does not show information about these listeners status but they are connected to ActiveMQ on startup. (Checking the ActiveMQ admin console)

EDIT 2: @JmsListener starts even auto-startup is set to false

I checked the jmsListenerEndpointRegistry for each container and I do not know if this is a bug or I am not correctly defining the configuration. However, I am just defining the container factory as explained before with AUTO-START set to false and the both listeners are started and consuming messages (running).

From my Log file:

jmsListenerEndpointRegistry ID <org.springframework.jms.JmsListenerEndpointContainer#1>, Auto-Startup <false>, Running <true>
jmsListenerEndpointRegistry ID <org.springframework.jms.JmsListenerEndpointContainer#0>, Auto-Startup <false>, Running <true>
crm86
  • 1,394
  • 1
  • 21
  • 44
  • 1
    Are you doing an explicit `start()` on the application context? `autoStartup` only pertains to the context calling start during context initialization. It has no bearing when you call `start()` on the context after it is created, which starts all beans, regardless of `autoStartup`. – Gary Russell Sep 23 '16 at 12:50
  • No. I am just calling run () on spring boot. Could be invoked by a child run() ? – crm86 Sep 23 '16 at 13:03
  • Please, share on the GitHub some simple Spring Boot application from our side. I remember that there was a `start()` problem with Spring Cloud Stream, BTW... – Artem Bilan Sep 23 '16 at 13:04

2 Answers2

8

You must have something else going on - I just wrote a quick boot app (1.4.1) and the container is not started...

@SpringBootApplication
public class So39654027Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(So39654027Application.class, args);
        JmsListenerEndpointRegistry reg = context.getBean(JmsListenerEndpointRegistry.class);
        MessageListenerContainer listenerContainer = reg.getListenerContainer("foo");
        System.out.println(listenerContainer.isRunning());
    }

    @Bean(name = "queueContainerFactory")
    public JmsListenerContainerFactory<?> queueContainerFactory(ConnectionFactory cf) {

        ActiveMQConnectionFactory amqCf = (ActiveMQConnectionFactory) cf;
        amqCf.setTrustAllPackages(true);
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(amqCf);
        factory.setAutoStartup(false);
        return factory;
    }

    @JmsListener(id="foo", destination = "so39654027", containerFactory = "queueContainerFactory")
    public void listen(String foo) {
        System.out.println(foo);
    }

}

and...

2016-09-23 09:24:33.428  INFO 97907 --- [           main] com.example.So39654027Application        : Started So39654027Application in 1.193 seconds (JVM running for 2.012)
false

I suggest you use a debugger in the container's start() method to see why it's being started.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • 1
    It was my mistake. I was executing the JmsListenerEndpointRegistry twice.. Debug on start() was useful also. – crm86 Sep 23 '16 at 18:01
0

Order is important, factory.setAutoStartup(autoStartup) after configure.

@Bean
public JmsListenerContainerFactory<?> ShipmentListenerFactory(@Qualifier("GSUBCachingConnectionFactory") CachingConnectionFactory connectionFactory,
                                                          DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    // This provides all boot's default to this factory, including the message converter

    // Added ability to disable not start listener
    boolean autoStartup = env.getProperty("app-env.CKPT_QUEUE_AUTO_START",Boolean.class,true);
    log.info("[MQ] CKPT_QUEUE_AUTO_START:{}",autoStartup);

    configurer.configure(factory, connectionFactory);
    factory.setAutoStartup(autoStartup);
    // You could still override some of Boot's default if necessary.
    return factory;
}