由于特定的Spring JMS配置,无法从Tomcat中取消部署

时间:2016-02-03 12:32:40

标签: java spring tomcat activemq spring-jms

我已经将ActiveMQ用作JMS实现(activemq-spring 5.12.1)和Spring JMS集成(spring-jms 4.2.3.RELEASE),所有这些都包含在Spring Boot Web应用程序中,部署在Tomcat上。

我遵循Spring配置(代码样本的详细程度减少了代码):

@Configuration
@EnableJms
public class AppConfiguration {
    @Bean
    public XAConnectionFactory jmsXaConnection(String activeMqUsername, String activeMqPassword) {
        ActiveMQXAConnectionFactory activeMQXAConnectionFactory = new ActiveMQXAConnectionFactory(activeMqUsername, activeMqPassword, activeMqUrl);
        ActiveMQPrefetchPolicy prefetchPolicy = new ActiveMQPrefetchPolicy();
        prefetchPolicy.setAll(0);
        activeMQXAConnectionFactory.setPrefetchPolicy(prefetchPolicy);
        return activeMQXAConnectionFactory;
    }

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory, JtaTransactionManager jtaTransactionManager) {
        DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
        containerFactory.setConnectionFactory(connectionFactory);
        containerFactory.setTransactionManager(jtaTransactionManager);
        containerFactory.setSessionTransacted(true);
        containerFactory.setTaskExecutor(Executors.newFixedThreadPool(2));
        containerFactory.setConcurrency("2-2");
        containerFactory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER);
        return containerFactory;
    }
}

我的目标是配置两个使用者(因此concurrecny设置为2-2)并阻止任何消息缓存(因此预取策略设置为0)。

它有效,但会导致非常不愉快的副作用: 当我尝试通过Tomcat Manager取消部署应用程序时,它会暂停一段时间然后无限期地每秒产生以下DEBUG消息:

"DefaultMessageListenerContainer:563 - Still waiting for shutdown of 2 Message listener invokers"

因此,我每次都被迫杀死Tomcat进程。我做错了什么?

我的一个幸运镜头(ActiveMQ和Spring JMS的文档都没有用),是将预取策略设置为1而不是0.然后它优雅地取消部署,但我看不出它是如何关联的。

另外我很好奇,为什么要将缓存级别设置为CACHE_CONSUMER,ActiveMQ需要创建两个使用者。当使用外部事务管理器时保留默认设置(CACHE_NONE)时,只创建了一个使用者(而并发仍然设置为2 2-2,所以TaskExecutor)。

如果重要,对于连接工厂和事务管理器,使用Atomikos。我也可以粘贴它的配置,但似乎无关紧要。

1 个答案:

答案 0 :(得分:0)

这很可能意味着消费者线程被“卡在”用户代码中;使用jstack进行线程转储以查看容器线程正在做什么。