【问题标题】:java websphere MQjava websphere MQ
【发布时间】:2013-01-03 18:39:55
【问题描述】:

我的目标是使用 WebSphere MQ Java 编程将 n 条消息放在一个 for 循环中的 WebSphere MQ 队列中。

我的 java 程序将作为独立程序运行。

如果中间有任何异常,我需要回滚所有消息。

如果没有例外,那么我应该提交所有消息。

在我完全完成之前,外界不应该看到我在队列中的消息。 我如何做到这一点?

根据 T.Rob 的回复更新了示例代码:

请检查示例代码是否正常?

设置 MQGMO_SYNCPOINT 是否仅与我的程序调用有关? (因为并行运行的类似程序也会将消息放在同一个队列中,并且这些消息不应受到我程序的 SYNCPOINT 的影响。)

public void sendMsg() {
        MQQueue queue = null;
        MQQueueManager queueManager = null;
        MQMessage mqMessage = null;
        MQPutMessageOptions pmo = null;
        System.out.println("Entering..");
        try {
            MQEnvironment.hostname = "x.x.x.x";
            MQEnvironment.channel = "xxx.SVRCONN";
            MQEnvironment.port = 9999;


            queueManager = new MQQueueManager("XXXQMANAGER");
            int openOptions = MQConstants.MQOO_OUTPUT;      
            queue = queueManager.accessQueue("XXX_QUEUENAME", openOptions, null, null, null);

            pmo = new MQPutMessageOptions(); 
            pmo.options = CMQC.MQGMO_SYNCPOINT;


            String input = "testing";
            System.out.println("sending messages....");
            for (int i = 0; i < 10; i++) {
                input = input + ": " + i;
                mqMessage = new MQMessage();
                mqMessage.writeString(input);
                System.out.println("Putting message: " + i);
                queue.put(mqMessage, pmo);

            }
            queueManager.commit();
            System.out.println("Exiting..");

        } catch (Exception e) {
            e.printStackTrace();
            try {
                System.out.println("rolling back messages");
                if (queueManager != null)
                    queueManager.backout();
            } catch (MQException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if (queue != null)
                    queue.close();
                if (queueManager != null)
                    queueManager.close();
            } catch (MQException e) {
                e.printStackTrace();
            }
        }
    }

【问题讨论】:

  • 一般QMgr环境和连接都是在程序中完成一次,在Send Message方法之外,但是循环是正确的。设置同步点选项,放置/获取消息,完成后提交。是的,同步点只是你的程序,实际上范围是拥有连接的线程。具有多个连接的单个程序可以同时具有多个独立的工作单元,所有这些都在一个队列上,并且可以按预期工作。

标签: java jakarta-ee ibm-mq


【解决方案1】:

WMQ 支持本地和全局 (XA) 工作单元。只需指定选项即可使用本地工作单元。正如 keithkreissl 在另一个答案中提到的那样,全局 XA 事务需要事务管理器。

对于您所描述的,一个 POJO 在同步点下进行消息传递,请在您的 MQGetMessageOptions 中指定 MQC.MQGMO_SYNCPOINT。当您准备好提交时,发出MQQManager.commit()MQQManager.backout() 调用。

请注意,ggrandes 提供的响应和文档是指 JMS 而不是 Java 类。 Java 类使用 WMQ 过程 API 的 Java 等效项,可以支持多个线程 (doc),甚至提供连接池 (doc)。请参阅 Java 文档而不是 JMS 文档以了解正确的行为。另外,我已经链接到最新的WMQ Java V7.5 client 附带的 WMQ V7.5 文档。后面的客户端有更多的本地功能(跟踪、灵活的安装路径、MQClient.ini 等)并与后级 QMgrs 一起使用。强烈建议使用最新版客户端,免费下载。

【讨论】:

    【解决方案2】:

    您只需要创建一个启用事务的会话。

    Session session;
    // ...
    boolean transacted = true;
    session = connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
    try {
        // ...do things...
        session.commit();
    } catch (Exception e) {
        session.rollback();
    }
    // ...
    

    警告注意:会话不是线程安全的;-)

    【讨论】:

      【解决方案3】:

      如果您有权访问事务管理器,更重要的是连接到您的 MQ 访问的 XATransaction,您可以在消息处理开始时启动事务,将所有消息放在队列中,然后提交事务。使用 XATransactions 在事务提交之前它不会放置任何消息。如果您无权访问它,您可以通过将消息放在本地数据对象中进行更多检查,如果没有异常遍历发送消息的本地数据对象,则将代码包装在 try/catch 中。后一种方法的问题是它会提交您的所有其他处理,但如果在发送消息时出现问题,您的其他处理将不会回滚。

      【讨论】:

      • 或者只使用原生的 WMQ 本地事务能力。所有 WMQ API 都包括在 GET 或 PUT 调用中指定 SYNCPOINT 以及 COMMIT 动词或 QMgr 方法。无需外部事务协调器或花哨的编程。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-27
      • 2011-03-10
      • 2013-04-06
      • 2011-02-10
      相关资源
      最近更新 更多