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