我有一个问题,试图优雅地关闭Tomcat(8)永远不会完成,因为看起来DefaultMessageListenerContainer
被无限期地阻塞(或循环)。
我一直在谷歌搜索解决方案,但我发现的任何类似的东西都没有用。这包括(但不限于):
configureListenerContainer()
设置容器的taskExecutor Messages.queue()
代替Messages.direct()
ActiveMQConnectionFactory
包裹在CachingConnectionFactory
一个简单的Servlet 3.0示例:
compile 'org.springframework.integration:spring-integration-core:4.3.6.RELEASE'
compile 'org.springframework.integration:spring-integration-jms:4.3.6.RELEASE'
compile 'org.springframework.integration:spring-integration-java-dsl:1.2.1.RELEASE'
初始化器:
public class ExampleWebApp implements WebApplicationInitializer {
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final AnnotationConfigWebApplicationContext springContext = new AnnotationConfigWebApplicationContext();
springContext.register(ExampleConfig.class);
servletContext.addListener(new ContextLoaderListener(springContext));
final ServletRegistration.Dynamic registration = servletContext.addServlet("example", new HttpRequestHandlerServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/status");
}
}
配置:
@Configuration
@EnableIntegration
public class ExampleConfig {
@Bean
public ConnectionFactory connectionFactory() {
final ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory();
mqConnectionFactory.setBrokerURL("tcp://host:port");
mqConnectionFactory.setUserName("----");
mqConnectionFactory.setPassword("----");
return mqConnectionFactory;
}
@Bean
public Queue testQueue() {
return new ActiveMQQueue("test.queue");
}
@Bean
public MessageChannel testReceiveChannel() {
return MessageChannels.direct().get();
}
@Bean
public IntegrationFlow pushMessageInboundFlow() {
return IntegrationFlows
.from(Jms.messageDrivenChannelAdapter(connectionFactory())
.destination(testQueue()))
.log()
.transform(new JsonToObjectTransformer(TestMessageObject.class))
.channel(testReceiveChannel())
.get();
}
/** Example message object */
public static class TestMessageObject {
private String text;
public String getText() {
return text;
}
public void setText(final String text) {
this.text = text;
}
}
}
如果我尝试通过catalina.sh脚本停止此操作(例如,按下"停止"在Intellij",它永远不会完成现有。到目前为止,我唯一的方法是能够关闭完成是通过一个小帮助类手动"在关机时销毁JmsMessageAdapters:
public class JmsMessageListenerContainerLifecycleManager {
private static final Logger LOG = LoggerFactory.getLogger(JmsMessageListenerContainerLifecycleManager.class);
@Autowired
private List<IntegrationFlow> mIntegrationFlows;
@PreDestroy
public void shutdownJmsAdapters() throws Exception {
LOG.info("Checking {} integration flows for JMS message adapters", mIntegrationFlows.size());
for (IntegrationFlow flow : mIntegrationFlows) {
if (flow instanceof StandardIntegrationFlow) {
final StandardIntegrationFlow standardFlow = (StandardIntegrationFlow) flow;
for (Object component : standardFlow.getIntegrationComponents()) {
if (component instanceof JmsMessageDrivenChannelAdapter) {
final JmsMessageDrivenChannelAdapter adapter = (JmsMessageDrivenChannelAdapter) component;
LOG.info("Destroying JMS adapter {}", adapter.getComponentName());
adapter.destroy();
}
}
}
}
}
}
虽然这有效,但它肯定是错误的解决方案。
以前我使用的是spring-integration的XML配置,我没有遇到这个问题。我错过了什么?
答案 0 :(得分:1)
唉!这绝对是个错误。看起来你正确地解决了它。
虽然考虑在那里销毁任何DisposableBean
。
我将修复程序添加到Spring Integration Java DSL。我们将在Spring Integration 1.2.2
之后发布下一个4.3.9
。
Spring Integration 5.0
将在明天的M3
版本中修复。