【问题标题】:JMS queue receive message?JMS 队列接收消息?
【发布时间】:2012-01-19 12:29:13
【问题描述】:

在 JMS API 文档中,它说:

public Message receive() throws JMSException

接收下一条消息 为此消息消费者生成。此调用无限期阻塞 直到产生消息或直到此消息使用者关闭。

如果此接收是在事务中完成的,则消费者会保留消息直到事务提交。

这里我有三个问题: 1.在代码中,我们需要while-loop来接收消息吗?喜欢:

while(true){
    Message msg = queue.receive();
    ....
}
  1. 什么是交易设置?如何提交交易?像这样:

    boolean transacted = false;
    session = connection.createQueueSession(transacted, Session.AUTO_ACKNOWLEDGE);
    
  2. receiveNoWait() 有事务支持吗?怎么用?

谢谢

【问题讨论】:

    标签: java jms


    【解决方案1】:
    1. 如果您要使用接收,那么您将需要某种循环来在收到第一个消息后继续接收消息。请记住,您还可以设置消息侦听器并通过回调方法异步获取接收到的消息,而不必阻塞。

    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 服务器带来了开销,因为在您提交之前它无法释放消息。
    • 您还可以查看以下关于 JMS with Java 的一些性能建议:precisejava.com/javaperf/j2ee/JMS.htm
    • 如何查看此邮件的重新投递次数?如果会话提交,会话仍然存在?能收到下一条消息吗?
    • 重新传递计数取决于 JMS 提供程序。他们中的许多人会在可配置的尝试次数后自动将消息发送到死信队列。因此,您可能根本不需要支持它,只需调用回滚即可。提交会话后,新会话会自动启动。
    • 你的意思是,如果没有提交会话,那么下一条消息将不会到达?
    猜你喜欢
    • 2011-06-14
    • 2012-05-06
    • 2013-08-01
    • 2021-03-29
    • 2018-01-28
    • 1970-01-01
    • 2019-10-08
    • 2010-09-19
    • 2012-11-16
    相关资源
    最近更新 更多