从Spring批处理步骤中听取JMS的最简洁方法是什么?

时间:2016-02-24 20:34:40

标签: activemq spring-batch spring-jms

Spring批处理文档建议使用JmsItemReader,它是JMSTemplate的包装器。但是,我发现JMSTemplate存在一些问题 - 请参阅http://activemq.apache.org/jmstemplate-gotchas.html

这篇文章引起了我的注意,因为在我真正读取它的数据之前,队列似乎消失了。错过消息的机会对我来说似乎是一个相当重要的问题。

2 个答案:

答案 0 :(得分:0)

对于消费者至少尝试使用DefaultMessageListenerContainer加上SingleConnectionFactory或任何此类连接工厂,它不需要调度程序来唤醒它们。这里有解释这个例子的日志,这个解释东西非常好 http://bsnyderblog.blogspot.com/2010/05/tuning-jms-message-consumption-in.html

答案 1 :(得分:0)

这是我最终解决的问题。由于查询是关于从弹簧批处理步骤中听取JMS的“最干净”的方式,因此我将打开问题一段时间,以防万一有更好的方法。

如果有人能弄清楚代码格式不正确的原因,请告诉我如何修复它。

<强> 1。在作业监听器中,分别在beforeJob和afterJob事件中实现队列设置和拆除:

public void beforeJob(JobExecution jobExecution) {
    try {
        jobParameters = jobExecution.getJobParameters();

        readerConnection = connectionFactory.createConnection();
        readerConnection.start();

    } catch (JMSException ex) {
        // handle the exception as appropriate
    }
}

public void afterJob(JobExecution jobExecution) {
    try {
        readerConnection.close();
    } catch (JMSException e) {
        // handle the exception as appropriate
    }
}

<强> 2。在阅读器中,实现StepListener和beforeStep / afterStep方法。

public void beforeStep(StepExecution stepExecution) {
    this.stepExecution = stepExecution;
    this.setJobExecution(stepExecution.getJobExecution());
    try {
        this.connection = jmsJobExecutionListener.getReaderConnection();
        this.jmsSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        this.messageConsumer = jmsSession.createConsumer(jmsJobExecutionListener.getQueue());
    }
    catch (JMSException ex)
    {
        // handle the exception as appropriate
    }

}

public ExitStatus afterStep(StepExecution stepExecution) {
    try {
        messageConsumer.close();
        jmsSession.close();
    } catch (JMSException e) {
        // handle the exception as appropriate
    }
    return stepExecution.getExitStatus();
}

第3。实现read()方法:

public TreeModel<SelectedDataElementNode> read() throws Exception,
        UnexpectedInputException, ParseException,
        NonTransientResourceException {

    Object result = null;

    logger.debug("Attempting to receive message on connection: ", connection.toString());

    ObjectMessage msg = (ObjectMessage) messageConsumer.receive();
    logger.debug("Received: {}", msg.toString());

    result = msg.getObject();
    return result;
}

<强> 4。根据需要将侦听器添加到Spring Batch上下文:

<batch:job id="doStuff">
    <batch:listeners>
        <batch:listener ref="jmsJobExecutionListener" />
    </batch:listeners>
... snip ...
            <batch:step id="step0003-do-stuff">
                <batch:tasklet transaction-manager="jtaTransactionManager"
                    start-limit="100">
                    <batch:chunk reader="selectedDataJmsReader" writer="someWriter"
                        commit-interval="1" />
                </batch:tasklet>
                <batch:listeners>
                    <batch:listener ref="selectedDataJmsReader" />
                </batch:listeners>
            </batch:step>
</batch:job>