为什么JMS会两次发送消息?

时间:2014-04-28 20:09:50

标签: jms

我使用JMS执行一些长时间运行的导入过程,但遇到一些重复的消息问题,我不太明白。

流程如下。一些支持bean代码将消息发送到消息Bean。消息bean接收此消息,轮询第三方服务,然后如果要导入新数据,则将这些行提交到数据库中。问题是JMS在我的导入过程需要一些时间,大约60秒左右的情况下发送我的消息两次。如果没有要导入的新行,并且该过程需要30秒左右,则该消息仅发送一次。

我认为它与确认消息收据有关,所以我做的第一件事(因为自动确认没有工作)将QueueSession设置为Session.CLIENT_ACKNOWLEDGE并放入msg.acknowledge()在我的onMessage方法中。可悲的是,这些消息仍然被发送了两次。

在此期间不会抛出任何错误代码或异常。

这是代码。

在Backing Bean中

public MyBackingBean(){
    try {
        InitialContext ctx = new InitialContext();
        qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
        qcon = qconFactory.createQueueConnection();
        qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

        queue = (javax.jms.Queue) ctx.lookup(IMPORT_QUEUE);
        qsender = qsession.createSender(queue);
        qsender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        qcon.start();

    } catch (JMSException e) {
        System.out.println(e);
    } catch (NamingException e) {
        System.out.println(e);
    }

public void startImport() {
        try {
            // send a JMS message for the long running job
            MapMessage mapMessage = qsession.createMapMessage();
            mapMessage.setObjectProperty("ipAddress", "127.0.0.1");
            qsender.send(mapMessage);
        } catch (JMSException e) {
            e.printStackTrace();
        } catch (Throwable te) {
            te.printStackTrace();
        }
}

导入消息Bean

@Override
public void onMessage(Message msg) {
    try {
           // create an ADF Application Module
           // poll a third party for some data
           // copy these rows (if new) and then 
           // commit via the ADF Application Module
        }
    catch (Exception e){
       // no errors are being thrown
    }
}

现在,我通过检查邮件是否是重新发送(msg.getJMSRedelivered())并忽略副本来忽略副本,但我对创可贴不太满意

有人对此有一些指示吗?

1 个答案:

答案 0 :(得分:1)

Will,我无法确定发生了什么,但是意识到,使用AUTO_ACKNOWLEDGE,确认实际上不会发生,直到线程从onMessage()调用返回。因此,如果您在onMessage()电话中花费60秒,我对重新发送并不感到惊讶。 使用CLIENT_ACKNOWLEDGE,通过调用msg.acknowledge(),您应该明确地确认该消息。但是,你在什么时候这样做?在onMessage()上花了60秒?那么你会得到同样的行为,我期待。 您可以在输入onMessage()调用后立即调用msg.acknowledge(),但意识到这意味着如果onMessage()方法中的某些内容崩溃,则不会重新传递该消息。但看起来你似乎还没有使用持续交付,所以也许你不在乎。

这是一个很好的参考;

http://www2.sys-con.com/itsg/virtualcd/Java/archives/0604/chappell/index.html#s1

相关问题