使用多线程侦听器处理JMS事务和重新传递

时间:2018-02-05 15:13:44

标签: jms advanced-queuing

我正在使用JMS处理Java 1.8 SE环境中的消息。消息源自Oracle Advanced Queue。因为处理消息可能需要一段时间,所以我决定拥有一个包含5个工作线程的池(MessageHandler对象),这样多个线程就可以同时处理消息。我希望在没有重复邮件传递的情况下保证交付。

我用

queueConnection.createQueueSession(true, Session.SESSION_TRANSACTED);

创建QueueSession。我使用下面的代码来处理传入的消息。基本上,onMessage会产生一个处理消息的线程。

public class JmsQueueListener implements MessageListener
{
    /** A pool of worker threads for handling requests. */
    private final ExecutorService pool;

    OracleJmsQueue queue;

    public void onMessage(Message msg)
    {
        pool.execute(new MessageHandler(msg));
        // can't commit here - the thread may still be processing
    }

    /**
     * This class provides a "worker thread" for processing a message
     * from the queue.
     */
    private class MessageHandler implements Runnable {

        /**
         * The message to process
         */
        Message message;

        /**
         * The constructor stores the passed in message as a field
         */
        MessageHandler(Message message) {
            this.message = message;
        }

        /**
         * Processes the message provided to the constructor by
         * calling the appropriate business logic.
         */
        public void run() {
            QueueSession queueSession = queue.getQueueSession();
            try {
                String result = requestManager.processMessage(message);

                if (result != null) {
                    queueSession.commit();
                }
                else {
                    queueSession.rollback();
                }
            }
            catch (Exception ex) {
                try {
                    queueSession.rollback();
                }
                catch (JMSException e) {
                }
            }
        }
    }   //  class MessageHandler

我的问题是我不知道如何向始发队列指示处理是否已成功完成。我无法在onMessage结束时提交,因为该线程可能尚未完成处理。我不认为我目前commitrollback的位置也不错。例如,如果5个工作线程处于各种完成状态,那么提交的队列会话的状态是什么?

我认为我必须缺少一些关于如何以多线程方式处理JMS的基本概念。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您正在使用异步消息处理,因此,除非您实现一种确保按时间顺序完成每个消息处理的方法,否则您将最终在最近的消息处理之后完成较旧的消息处理。那么为什么要使用消息传递服务?

问题的简单解决方案是在commit方法结束时onMessage,在messageHandler正文中,如果出现错误,请重新排队。但是,如果重新入队本身失败,则此解决方案可能会出现问题。