用Spring 的 JmsTemplate 来接收消息时, 按照其文档:
/*
Default settings for JMS Sessions are "not transacted" and "auto-acknowledge". As defined by the J2EE specification, the transaction and acknowledgement parameters are ignored when a JMS Session is created inside an active transaction, no matter if a JTA transaction or a Spring-managed transaction. To configure them for native JMS usage, specify appropriate values for the "sessionTransacted" and "sessionAcknowledgeMode" bean properties.
*/
按照JMS 规范, 如果是在事务内部接收消息, 会忽略sessionAcknowledgeMode 选项, Session.sessionAcknowledgeMode 总是 auto-acknowledge. 如果在事务外部调用,默认是 auto-acknowledge的, 如果需要定义为其他 acknowledge mode, 设置sessionTransacted 和sessionAcknowledgeMode属性. 但是, 当我设置sessionTransacted为false, sessionAcknowledgeMode为 client acknowledge 时, 如果调用消息的 acknowledge 方法, 会抛出异常, 因为每次接收完了消息, JmsTemplate 会将 Session 和 Connection 都关闭. 而且消息也是auto-acknowledge的.
查看JmsTemplate 的原代码,发现:
最终接收消息的代码会进入这个方法:
protected Message doReceive(Session session, MessageConsumer consumer)
这是个 protected 方法, subclass 可以 override 它.
于是跟踪进去看看里面的代码发现:
if (session.getTransacted()) {
// Commit necessary - but avoid commit call within a JTA transaction.
if (isSessionLocallyTransacted(session)) {
// Transacted session created by this template -> commit.
JmsUtils.commitIfNecessary(session);
}
}
else if (isClientAcknowledge(session)) {
// Manually acknowledge message, if any.
if (message != null) {
message.acknowledge();
}
}
注意到这句: else if (isClientAcknowledge(session)) {
这就是在事务外部接收消息后的处理, 如果我们设置了Session 为 client acknowledge 模式, JmsTemplate 会在这里acknowledge 接收到的消息的.
刚好可以 override 这部分代码, 嵌入我们自己的处理, 让我们自己来决定是否 acknowledge 接收到的消息.
解决方法:
1)
public interface MessageHandler {
/**
* Process the message, if process finish successfully, return true, otherwise false
* return true if process successfully
*/
boolean processMessage(Message message);
}
2) Extend JmsTemplate, override JmsTemplate's method: protected Message doReceive(Session session, MessageConsumer consumer).
public class MyJmsTemplate extends JmsTemplate {
...
} else if (isClientAcknowledge(session)) {
// Manually acknowledge message if MessageHandler is not null and process message successfully
if (message != null) {
if (messageHandler == null || (messageHandler != null && messageHandler.processMessage(message)))
message.acknowledge();
}
}
3) Sample MessageHandler
public class SampleMessageHandler implements MessageHandler {
@Override
public boolean processMessage(Message message) {
try {
int flag = message.getIntProperty("flag");
return (flag < 2);
} catch (JMSException e) {
e.printStackTrace();
return false;
}
}
}
4) 测试时, 设置一下sssionTransacted 和 sssionAcknowledgeMode.
<bean id="myJmsTemplate" class="com.zero.demo.jms.MyJmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="authReplyDestination"/>
<property name="sessionTransacted" value="false"/>
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/>
<property name="messageHandler">
<bean class="com.zero.demo.jms.SampleMessageHandler"/>
</property>
</bean>
分享到:
相关推荐
- 考虑到事务管理,根据业务需求选择合适的事务配置,例如`CLIENT_ACKNOWLEDGE`或`AUTO_ACKNOWLEDGE`等确认模式。 - 如果遇到性能问题,可以考虑调整WebLogic Server的JMS配置,如缓存大小、并发消费者数量等。 ...
在`pom.xml`文件中,我们需要添加`spring-boot-starter-jms`和`activemq-client`依赖,以便利用Spring JMS API和ActiveMQ客户端库。 ```xml <groupId>org.springframework.boot <artifactId>spring-boot-...
- CLIENT_ACKNOWLEDGE:客户端通过消息的acknowledge方法手动确认。 - DUPS_ACKNOWLEDGE:延迟确认,可能造成消息重复。 2. **持久性(Durability)** 消息可以设置为持久性(PERSISTENT)或非持久性(NON_...
<jms:listener-container connection-factory="connectionFactory" acknowledge="auto"> <jms:listener destination="myQueue" ref="messageListener" /> </jms:listener-container> ``` 最后,在Java代码中,...
9. **消息确认**:ActiveMQ支持两种确认模式:自动确认(Auto Acknowledge)和客户端确认(Client Acknowledge)。客户端确认允许应用在适当的时候手动确认消息已被处理,以防止消息丢失。 10. **故障转移和集群**...
关于消息的确认,ActiveMQ支持两种确认模式:自动确认(auto-acknowledge)和手动确认(client-acknowledge)。默认情况下,ActiveMQ使用自动确认模式,即消息一旦被消费就会自动确认。如果你希望在处理完消息后再...
总结来说,"activemq + spring"的主题涵盖了使用Java原生API连接ActiveMQ以及通过Spring框架实现更高级别的整合,包括利用Spring的JMS支持简化消息发送和接收。这些知识对于构建基于消息驱动的分布式系统,实现解耦...
JMS消息确认(Acknowledgment)是指客户端确认收到JMS消息的机制,可以使用acknowledge方法来确认消息的收到。 高级消息队列协议(AMQP) 高级消息队列协议(AMQP)是一种针对面向消息中间件的开放标准应用层协议...
<jms:listener-container connection-factory="connectionFactory" acknowledge="auto"> <jms:listener destination="myQueue" ref="messageListener" /> </jms:listener-container> ``` 在这里,我们创建了一...
在`pom.xml`文件中,你需要引入Spring Boot的`spring-boot-starter-jms`和ActiveMQ的客户端库: ```xml <groupId>org.springframework.boot <artifactId>spring-boot-starter-jms <groupId>org.apache....
<jms:listener-container connection-factory="connectionFactory" acknowledge="auto"> <jms:listener destination="myQueue" ref="messageListener" method="onMessage"/> </jms:listener-container> ``` ...
- **集成Spring框架**:能够无缝地集成到使用Spring的应用程序中,并支持Spring 2.0的新特性。 - **兼容主流服务器**:已经过Geronimo、JBoss、GlassFish和WebLogic等主流J2EE服务器的测试,并可通过JCA 1.5 ...
此外,对于大型项目,通常会使用Spring框架的JMS支持来简化消息队列的集成和管理。 这个实例只是基础,要完全掌握Java MES发消息,还需要深入学习和实践,包括理解不同的消息模型(点对点、发布/订阅),优化性能,...