Activemq 从Spring批处理步骤内部侦听JMS的最干净的方法是什么?

Activemq 从Spring批处理步骤内部侦听JMS的最干净的方法是什么?,activemq,spring-batch,spring-jms,Activemq,Spring Batch,Spring Jms,Spring批处理文档建议使用JmsItemReader,它是JMSTemplate的包装器。但是,我发现JMSTemplate存在一些问题—请参阅 这篇文章引起我的注意,只是因为队列在我真正读取数据之前就消失了。错过消息的机会对我来说似乎是一个相当重要的问题。对于消费者来说,至少可以尝试使用DefaultMessageListenerContainer和SingleConnectionFactory或任何类似的连接工厂,它不需要调度程序来唤醒他们。有很多例子可以解释这一点,这一个非常适合解释这

Spring批处理文档建议使用JmsItemReader,它是JMSTemplate的包装器。但是,我发现JMSTemplate存在一些问题—请参阅


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

对于消费者来说,至少可以尝试使用DefaultMessageListenerContainer和SingleConnectionFactory或任何类似的连接工厂,它不需要调度程序来唤醒他们。有很多例子可以解释这一点,这一个非常适合解释这些东西

这是我最终得到的解决方案。由于该查询是关于从spring批处理步骤中侦听JMS的“最干净”的方法,因此我将把这个问题保留一段时间,以防有更好的方法

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

1。在作业侦听器中,分别在作业前和作业后事件中实现队列设置和拆卸:

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
    }
}
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;
}
<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>
2。在reader中,实现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 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
    }
}
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;
}
<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>
public TreeModel read()引发异常,
UnexpectedInputException,ParseException,
非TransientResourceException{
对象结果=空;
debug(“试图在连接上接收消息:”,connection.toString());
ObjectMessage msg=(ObjectMessage)messageConsumer.receive();
debug(“Received:{}”,msg.toString());
结果=msg.getObject();
返回结果;
}
4。根据需要将侦听器添加到Spring批处理上下文中:

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

... 剪

在我看来,这似乎是相关的,因为他报告的症状正是apache post描述的感谢反馈的症状。由于JMSTemplate在这种上下文中肯定会丢失消息,因此没有任何涉及JMSTemplate的解决方案是可行的答案。我不会贬低这个答案,因为我可能仍然遗漏了一些东西。