Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
让一个简单的SpringJMS客户端确认工作_Spring_Jms_Activemq - Fatal编程技术网

让一个简单的SpringJMS客户端确认工作

让一个简单的SpringJMS客户端确认工作,spring,jms,activemq,Spring,Jms,Activemq,我刚开始想办法在春季获得jmsactivemq确认。到目前为止,我有一个消费者工作得很好,但当我不确认消息时,它仍然从队列中获取(我希望它留在那里或以死信队列结束) 在ConsumerClass中,我的简单consumer如下所示: @覆盖消息(消息消息)上的公共最终无效{ 对象postedMessage=null; 试一试{ postedMessage=((ObjectMessage)message.getObject(); if(postedMessage.getClass()==S

我刚开始想办法在春季获得
jmsactivemq确认。到目前为止,我有一个消费者工作得很好,但当我不确认消息时,它仍然从队列中获取(我希望它留在那里或以死信队列结束)


在ConsumerClass中,我的简单consumer如下所示:

@覆盖消息(消息消息)上的公共最终无效{
对象postedMessage=null;
试一试{
postedMessage=((ObjectMessage)message.getObject();
if(postedMessage.getClass()==SomeMessageType.class){
试一试{
//这里有些逻辑
message.acknowledge();
return;//此处成功
}捕获(MyException e){
error(“无法处理消息,但由于我没有调用acknowledge,我希望它最终会进入死消息队列”);
}
}
}捕获(JME){
logger.error(“从队列中提取消息时出错”,e);
}
//同样值得注意的是,如果我在这里抛出新的RuntimeException(“Aww Noos”);它将不会从队列中取出,但不会被消耗(或最终成为死信)。。。
}

在我的实践中,很少使用客户确认。典型的设置是自动确认,因此如果您的代码正常地从onMessage()返回(不存在异常),则会自动确认消息。若您的代码从onMessage()抛出异常,那个么并没有确认,消息通常会被重新传递到预先配置的次数,之后它通常会被丢弃或放入死消息队列

在您的案例中,从JMS服务器的角度来看,它看起来像是客户机请求消息,但从未确认,所以它仍然由客户机“处理”。在这种情况下,消息对于同一队列中的其他消费者来说是不可见的,因此您可能会得到这样的印象,即消息“离开队列”,而事实上它仍然在那里。显然,您也不会在死消息队列中看到这样的消息

我建议您阅读JMS规范,以清楚地了解不同的确认模式。

我在

如果您更改acknowledge=“Transact”并确保抛出新的RuntimeException(“消息无法被使用。回滚事务”),它似乎工作得很好;在OnMessage()例程的末尾


仍然不知道acknowledge=“client”实现了什么,尽管阅读此文档:SpringJMS容器不使用
消息。acknowledge()

侦听器容器提供以下消息确认选项:

“sessionAcknowledgeMode”设置为“AUTO_ACKNOWLEDGE”(默认值):在侦听器执行之前自动确认消息;如果引发异常,则不会重新交付。
“sessionAcknowledgeMode”设置为“CLIENT_ACKNOWLEDGE”:侦听器成功执行后自动确认消息;如果引发异常,则不会重新交付。
“sessionAcknowledgeMode”设置为“DUPS_OK_ACKNOWLEDGE”:侦听器执行期间或之后的延迟消息确认;引发异常时可能重新交付。
“sessionTransacted”设置为“true”:侦听器成功执行后的事务确认;在引发异常的情况下保证重新交付


使用下面的代码它将工作

<bean id="{containerName}"  class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref={connectionFactoryBean} />
    <property name="destinationName" ref="{queue}" />
    <property name="messageListener" ref="{listner}" />
    <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/>
</bean>

对消费者中的消息调用acknowledge()方法

考虑以下场景:应用程序接收但不确认消息。应用程序接收后续消息并确认该消息。前一条信息会发生什么变化?前一条消息也被视为已确认。通常,确认特定消息会确认会话收到的所有先前消息。在上述输出中,只有消息5被明确确认。消息5之前的所有消息都被隐式确认。消息5之后的消息不被确认

有关更多详细信息,请参阅


另外请查看本文

如今,Spring在普通的
JMS
消息侦听器上提供了良好的包装器

参见的JavaDocs

“sessionAcknowledgeMode”
设置为
“客户端确认”
:成功执行侦听器后自动确认消息;在引发用户异常以及其他侦听器执行中断(例如
JVM
正在消亡)的情况下,尽最大努力重新交付


因此,当您定义一个方法时,确认成功完成后会自动发送,但您可以抛出一个异常以再次接收消息。

很抱歉,在这种情况下,如果我在消息之后返回,则确认成功。acknowledge()(我在代码示例中添加了此项)如果我取消对抛出RuntimeException的注释,也会成功(必须是运行时才能满足MessageListener接口)我得到一个错误:08:39:59066 WARN org.springframework.jms.listener.DefaultMessageListenerContainer#0-2 listener.DefaultMessageListenerContainer:694-jms消息侦听器的执行失败,并且没有设置错误处理程序。java.lang.RuntimeException:Aww Noos我可以看到,在这种情况下,消息被消费者保留,直到我终止吃了它,这时他们会试图在另一个消费者身上消费,让我觉得acknowledge=“client”实际上什么都不做,如果我读对了javadoc,“auto”会在调用侦听器之前进行确认:“sessionacknowledgeemode”设置为“auto_acknowledge”(默认值):在侦听器执行之前自动确认消息;在引发异常的情况下不会重新传递。”源文档:javax.jms.Session.AUTO_ACKNOWLEDGE供任何困惑的人使用。