Java 由于特定的SpringJMS配置,无法从Tomcat取消部署

Java 由于特定的SpringJMS配置,无法从Tomcat取消部署,java,spring,tomcat,activemq,spring-jms,Java,Spring,Tomcat,Activemq,Spring Jms,我使用ActiveMQ作为JMS实现(ActiveMQSpring5.12.1)和SpringJMS集成(SpringJMS 4.2.3.RELEASE),所有这些都包装在SpringBootWeb应用程序中,部署在Tomcat上 我有以下Spring配置(代码因代码示例的冗长而减少): 我的目标是配置两个使用者(因此concurrecny设置为2-2)并防止任何消息缓存(因此预取策略设置为0) 它有效,但会产生非常不愉快的副作用: 当我试图通过Tomcat Manager取消部署应用程序时,它

我使用ActiveMQ作为JMS实现(
ActiveMQSpring5.12.1
)和SpringJMS集成(
SpringJMS 4.2.3.RELEASE
),所有这些都包装在SpringBootWeb应用程序中,部署在Tomcat上

我有以下Spring配置(代码因代码示例的冗长而减少):

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

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

“DefaultMessageListenerContainer:563-仍在等待关闭2个消息侦听器调用程序”

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

我的幸运之举之一(ActiveMQ和SpringJMS的文档都没有那么大帮助)是将预回迁策略设置为1而不是0。然后它优雅地展开,但我看不出它是如何关联的

我也很好奇,为什么ActiveMQ需要将缓存级别设置为
cache\u CONSUMER
,才能创建两个使用者。当保留默认设置时(
CACHE\u NONE
在使用外部事务管理器时),只创建了一个使用者(而并发仍然设置为两个2-2,
TaskExecutor


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

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

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