【问题标题】:Stop MDB Message Redelivery停止 MDB 消息重新传递
【发布时间】:2016-09-02 12:58:31
【问题描述】:

我有一个 StatelessSessionBean,它在调用特定方法时会创建一个 MapMessage 以发送到 MDB。

QueueConnection connection = null;
QueueSession mSession = null;
QueueSender messageProducer = null;
try {
    QueueConnectionFactory connectionFactory = (QueueConnectionFactory) home(session).getCTX().lookup(DocumentManagementTransactionUtil.QUEUE_CONNECTION_FACTORY);
    connection = connectionFactory.createQueueConnection();
    mSession = connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
    Queue dest = (Queue) home.getCTX().lookup(DocumentManagementTransactionUtil.QUEUE_DESTINATION);
    messageProducer = mSession.createSender(dest);
    messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    messageProducer.send(createJMSMessageFordocMessageReceiver(mSession, session, idnr, debugCode));
} catch (Exception ex) {
    log.error("failed to start DocumentTransfer MDB", ex);
    throw new AsaleException("failed to start DocumentTransfer MDB", ex);
} finally {
    try { if (messageProducer != null) messageProducer.close(); } catch (Exception e) { }
    try { if (mSession != null) mSession.close(); } catch (Exception e) { }
    try { if (connection != null) connection.stop(); connection.close(); } catch (Exception e) { }
}


现在在我的 MDB 的 onMessage 方法中,我从我的消息中读出我需要的所有内容并确认它。

MapMessage msg = (MapMessage) message;
project = msg.getLong("project");
Long lang = msg.getLong("lang");
int firm = msg.getInt("opFirm");
int sub = msg.getInt("opSub");
long user = msg.getLong("user");
int debugCode = msg.getInt("debugCode");

log.debug(project + prelog + "DocumentManagementMDBean... Retrieved Message: User: " + user + " Project: " + project + " JMS MessageID: " + message.getJMSMessageID() + " Redelivered: " + message.getJMSRedelivered());
message.acknowledge();


并且开始一个冗长的操作,该操作需要一个未定义的时间(1 到 X 分钟)而不会从 onMessage 方法返回。

5 分钟后,从 ID 和 redelivered 状态可以看出,我的消息被重新发送,尽管我之前已确认。

我做错了什么还是有办法告诉系统不要重新传递消息?


编辑:
@TransactionManagement(TransactionManagementType.BEAN) @MessageDriven(mappedName = DocumentManagementTransactionUtil.MAPPED_NAME, activationConfig = { @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = DocumentManagementTransactionUtil.QUEUE_DESTINATION), @ActivationConfigProperty(propertyName = "dLQMaxResent", propertyValue = "0")})

【问题讨论】:

标签: jakarta-ee javabeans wildfly message-queue


【解决方案1】:

关于消息驱动 bean 的一切都是事务性的。

如果无法将消息传递到它的队列/主题,那么您的事务将失败并回滚。

如果由于任何原因无法处理消息,则执行 MDB 的事务将被回滚。在这种情况下,规范要求容器重试向 MDB 传递消息。

在您的情况下,您的事务似乎超时,随后任何事务操作(例如数据库访问或 EJB 调用)都将失败并引发异常。容器随后会重试处理该消息。

一般来说,您不应尝试在任何 EJB 方法(包括消息驱动 bean)中执行长时间运行的进程。

正如您使用 wildfly 标记的那样,我猜您正在使用 Java EE 7 实现。如果是这种情况,您可以考虑使用 JSR-352 批处理 API 来满足您的目的。

【讨论】:

    猜你喜欢
    • 2011-11-13
    • 2016-05-26
    • 2015-03-11
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 2012-02-07
    相关资源
    最近更新 更多