WebSphere 7 中的消息驱动 bean (EJB3)、XA 事务、错误处理

Posted

技术标签:

【中文标题】WebSphere 7 中的消息驱动 bean (EJB3)、XA 事务、错误处理【英文标题】:Message-driven bean (EJB3) in WebSphere 7, XA transactions, Error handling 【发布时间】:2012-01-08 03:47:34 【问题描述】:

我是 EJB 的新手。背景:我有一个使用 WebSphere 默认消息传递提供程序接收 MapMessages 的 MDB,它有一个 java.sql.DataSource 来做一些工作,使用preparedstatement、jdbc 事务等。我在 ibm-ejb-bnd.xml 和ejb-jar.xml 使用具有激活规范和目标名称的 JCA 适配器。我在 ejb-jar 和 ibm-ejb-jar-bind 中添加了一个 java.sql.DataSource。我还在 MessageListener 中添加了带有 @Resource 注释的 DataSource。

2 个场景我无法理解(第一个场景已修复,请参阅更新)...

容器管理的 MDB: DataSource 驱动程序与 XA 不兼容,因此我在 WebSphere 中启用了“最后参与者支持”。不过,当 MDB 事务类型设置为容器时,我在提交时收到错误:

[11/28/11 10:56:10:988 MST] 0000002e RegisteredRes E   WTRN0063E: An illegal attempt to commit a one phase capable resource with existing two phase capable resources has occurred.

也许这是因为在 DataSource 提交后,返回到 MessageListener 提交使其成为最后一个参与者?我相信 WAS 7 中的默认消息传递提供程序与 XA 兼容,尽管我还没有看到任何明确说明的文档。

消息在第一个错误后立即重新运行 4 次(即使根据 WebSphere 中的 ActivationSpec 应该有 30 秒的延迟)。每次抛出相同的错误。根据 MessageListener 它没有错误地完成,所以这个错误是美妙的隐形容器管理事务的一部分。我认为我不需要 XA 全局事务,因为除了 JMS 之外只有一个 DataSource,我以编程方式处理事务回滚。 JMS msg,MDB 也是异步的,AUTO-ACKNOWLEDGE。一旦收到消息,就可以确认。

如果我引入了应用程序错误,因此出现异常,我会立即看到此错误 5 次(无延迟):

[11/28/11 10:16:18:857 MST] 0000002b LocalExceptio E   CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "onMessage" on bean...

所以我切换到......

Bean 托管 MDB: 提交在没有 XA 错误的情况下工作,并且只发生一次。然而,错误处理仍然没有像我期望或想要的那样表现!在 MessageListener 类中,捕获的异常抛出了一个 EJB 异常,我认为这应该导致 MDB 具有我想要的行为:异常的原因对我来说并不重要,当 MDB 抛出一个捕获的异常时,不应该是否根据 WebSphereActivationSpec 中的属性重试 MDB? 而是消息转到 MessageListener 5 次,立即引发与容器管理 MDB 相同的错误:“EJB 引发了意外(未声明的)异常......”

如果我抛出 RuntimeException,则不会发生“未加速(未声明)预期”消息,但该消息仍会立即重试 4 次,而不是等待重试延迟。

感谢阅读,非常感谢任何帮助或见解!

更新:我最终通过将数据源切换为 XA 兼容解决了 XA 兼容性问题。在 WAS 管理控制台中:Resources->JDBC Providers->DB2 Universal JDBC Driver Provider->将实现类名更改为:com.ibm.db2.jcc.DB2XADataSource

当消息失败时,我仍然遇到同样的问题。它会立即重试,而不是根据 WAS 中的 ActivationSpec。

【问题讨论】:

【参考方案1】:

我相信激活规范中的重试间隔是关于关闭的连接,而不是失败的消息。

您应该在 SIB 目标中定义所需的时间间隔

巴士 > 巴士 > 目的地 > DESTINATION

查看异常目的地

每条消息的最大失败传递次数是消息在声明失败之前将被发送多少次(默认为 5 次,这就是为什么您会再收到 4 次)

当消息失败时,它将移动到异常目标队列,或者如果设置为 None 将在一定时间后重试,该时间在总线级别设置但可以为每个目标覆盖(请参阅覆盖消息传递引擎阻塞重试超时默认)

【讨论】:

谢谢,谢谢。我在多个论坛上问过这个问题,没有人回答。 不确定我是否应该问一个新问题并直接给您,但是否可以在消息被宣布为失败之前设置交付之间的延迟? 如果我记得您可以将其设置为失败或在特定时间间隔内开始重试,我认为您不能在失败前设置前 X 次的时间间隔。但我可能错了。【参考方案2】:

我不知道你是否还需要它,但你应该检查自定义属性: sib.processor.blockedRetryTimeout 为消息传递引擎定义。

这是您要搜索的内容,在消息等待重新传递期间,它处于 UNLOCKED 状态,因此可以丢弃。

【讨论】:

以上是关于WebSphere 7 中的消息驱动 bean (EJB3)、XA 事务、错误处理的主要内容,如果未能解决你的问题,请参考以下文章

JMS 的 Spring 配置(Websphere MQ - SSL、Tomcat、JNDI、非 IBM JRE)

消息驱动 Bean 两次读取相同的消息

Intellij IDEA 创建消息驱动Bean - 接收JMS消息

JBOSS EAP 7中的顺序消息处理

消息驱动的 bean 没有收到任何消息

是否可以在运行时手动将消息驱动 bean 订阅到 JMS 队列/主题?