JMS队列接收消息?

7
在JMS API文档中,它说:
public Message receive() throws JMSException

Receives the next message produced for this message consumer. This call blocks indefinitely until a message is produced or until this message consumer is closed.

If this receive is done within a transaction, the consumer retains the message until the transaction commits.

我是一个有用的助手,可以翻译文本。

这里有三个问题: 1. 在代码中,我们需要使用while循环来接收消息吗?例如:

while(true){
    Message msg = queue.receive();
    ....
}
  1. what is the transaction setting ? how to commit a transaction ? like this:

    boolean transacted = false;
    session = connection.createQueueSession(transacted, Session.AUTO_ACKNOWLEDGE);
    
  2. receiveNoWait() has transaction support ? how to use it ?

谢谢

1个回答

3
  1. 如果您要使用receive,则需要一些循环来保持在接收到第一个消息后继续接收消息。请记住,您还可以设置messagelistener并通过回调方法异步获取接收的消息,而无需阻塞。
  2. 默认情况下,事务通常设置为AUTO_ACKNOWLEDGE,这意味着从队列中获取消息后就会消失,无法回滚。如果要设置事务,则需要将会话设置为事务性,并将方法设置为SESSION_TRANSACTED。当您在会话上调用commit()时,消息将在队列上确认。
  3. 如果正确设置了确认模式并在会话上使用commit()和rollback(),则receiveNoWait()可以具有事务支持。

如果我是您,我会创建一个MessageListener,而不必担心旋转线程来轮询接收方法。请注意,一旦创建会话,隐式事务即开始。

public class JmsAdapter implements MessageListener, ExceptionListener
{
    private ConnectionFactory connFactory = null;
    private Connection conn = null;
    private Session session = null;

    public void receiveMessages() 
    {
        try
        {
            this.session = this.conn.createSession(true, Session.SESSION_TRANSACTED);

            this.conn.setExceptionListener(this);

            Destination destination = this.session.createQueue("SOME_QUEUE_NAME");

            this.consumer = this.session.createConsumer(destination);

            this.consumer.setMessageListener(this);

            this.conn.start();
        } 
        catch (JMSException e) 
        {
            //Handle JMS Exceptions Here
        }
    }

    @Override
    public void onMessage(Message message) 
    {
        try
        {
            //Do Message Processing Here

            //Message sucessfully processed...  Go ahead and commit the transaction.
            this.session.commit();
        }
        catch(SomeApplicationException e)
        {
            //Message processing failed.
            //Do whatever you need to do here for the exception.

            //NOTE: You may need to check the redelivery count of this message first
            //and just commit it after it fails a predefined number of times (Make sure you
            //store it somewhere if you don't want to lose it).  This way you're process isn't
            //handling the same failed message over and over again.
            this.session.rollback()
        }
    }
}

事务对JMS服务器造成了额外的开销,因为在提交之前它无法释放消息。 - gregwhitaker
您还可以查看以下内容,了解有关使用Java的JMS性能建议:http://www.precisejava.com/javaperf/j2ee/JMS.htm - gregwhitaker
如何检查此消息的重新传递计数?如果会话提交,会话仍然存在吗?它能接收下一条消息吗? - user595234
重新投递的次数取决于JMS提供者。其中许多会在可配置的尝试次数后自动将消息发送到死信队列。因此,您可能根本不需要支持它,只需要调用回滚。一旦提交了一个会话,新会话就会自动启动。 - gregwhitaker
你的意思是,如果不提交会话,那么下一条消息就不会到达了吗? - user595234

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接