1

对于某些上下文,我正在使用符合 jsr 的实现在 Spring 批处理中执行 JMS 读取器和写入器。我正在使用 Spring 批处理提供的 JMSReader 和 JMS 编写器类,但我将它们包装在我自己的阅读器和编写器中。由于我使用的是 JSR 方法,因此我没有可用的典型应用程序上下文。这些类是通过作业规范或根据 jsr 规范通过 batch.xml 初始化的。

我遇到的问题是我有一个独立的批处理应用程序,当我定义一个 JMS 读取器和/或 jms 编写器时,它为活动 mq 创建一个连接工厂并将其设置为 spring 的 JMSTemplate 类的目标工厂,完成后的应用程序处理未正确关闭。为 IBM MQ 使用连接工厂的替代方法可以正常工作。

让我提供一些我已经完成的代码。

这是我创建连接工厂的地方。我做了几行注释的更改,试图让那些在应用程序运行时还活着的线程死掉。

private ConnectionFactory openAMQ() throws IllegalArgumentException{
    ActiveMQConnectionFactory targetConnectionFactory = new ActiveMQConnectionFactory();

    if(protocol == null){
        throw new IllegalArgumentException("Active MQ protocol can not be empty");
    }

    AMQProtocols proto = AMQProtocols.valueOf(protocol.toUpperCase());

    StringBuilder sb = new StringBuilder();

    sb.append(proto.getProtocol()).append("://").append(this.host).append(":").append(this.port);

    if(amqParams != null && amqParams.trim().length() > 0){
        sb.append("?").append(amqParams);
    }

    targetConnectionFactory.setBrokerURL(sb.toString());
    //targetConnectionFactory.setAlwaysSessionAsync(false);
    //targetConnectionFactory.setUseAsyncSend(false);
    return targetConnectionFactory;
}

这是我创建 JMSTemplate 对象的地方

protected JmsTemplate getJMSTemplate(ConnectionFactory targetConnectionFactory){
    CachingConnectionFactory ccf = new CachingConnectionFactory();

    ccf.setTargetConnectionFactory(targetConnectionFactory);
    JmsTemplate template = new JmsTemplate(ccf);

    template.setDefaultDestinationName(jmsDefaultDestinationName);

    template.setReceiveTimeout(Long.parseLong(jmsReceiveTimeoutValue));
    template.setSessionTransacted(Boolean.parseBoolean(jmsSessionTransacted));
    //template.setMessageConverter(messageConverter);


    return template;
}

最后是 JMSReader 的 open 方法,作者几乎相同

public void open(Serializable checkpoint) throws Exception {

    //First we need to get our broker specific connection factory
    ConnectionFactory targetConnectionFactory = getTargetConnectionFactory();

    this.template = getJMSTemplate(targetConnectionFactory);

    reader = new JmsItemReader();
    reader.setItemType(Class.forName(jmsItemTypeFullyQualifiedName));
    reader.setJmsTemplate(template);

}

我看到的线程似乎与连接以及一些不活动的监视线程有关。由于它们保持活跃,它可以防止独立应用程序关闭。

有谁知道我如何配置连接工厂或 jms 模板以阻止这种情况发生,或者在阅读器完成后可能对其进行管理以使其正确关闭。

4

1 回答 1

0

我想我回答了我自己的问题。在 CachingConnectionFactory 上,我在 jms 读取器和写入器的 close 方法中添加了对 destroy 方法的调用。我确实担心调用不允许正确清理,但它允许应用程序关闭而不是挂起。

于 2015-10-23T20:43:13.473 回答