如何将MQ Server回复消息与正确的请求进行匹配

时间:2011-02-16 19:39:47

标签: queue jms websphere ibm-mq correlation

我正在连接IBM Websphere MQ。我希望能够将回复消息与正确的请求消息进行匹配。我已经浏览了数百页来获得这个并且没有运气。

我有一个类 - MQHandler - 它将消息发送到一个已定义的队列,并从另一个队列中读取请求。这很好,但是,如果多个用户同时使用该应用程序,则消息会混淆。

我似乎无法在接收器上获得指示CorrelationID匹配的方法。 有点像...

consumer.receive(selector);

您可以查看以下方法以确保我正确地执行此操作吗?

/**
 * When the class is called, this initialisation is done first.
 * 
 * @throws JMSException
 */
public void init() throws JMSException
{
    // Create a connection factory
    JmsFactoryFactory ff;
    try
    {
        ff = JmsFactoryFactory.getInstance( WMQConstants.WMQ_PROVIDER );
        cf = ff.createConnectionFactory();

        // Set the properties
        cf.setStringProperty( WMQConstants.WMQ_HOST_NAME, hostServer );
        cf.setIntProperty( WMQConstants.WMQ_PORT, 1414 );
        cf.setStringProperty( WMQConstants.WMQ_CHANNEL, channel );
        cf.setIntProperty( WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT );
        cf.setStringProperty( WMQConstants.WMQ_QUEUE_MANAGER, qManager );

        connection = cf.createConnection();

        session = connection.createSession( false, Session.AUTO_ACKNOWLEDGE );
    }
    catch( JMSException e )
    {
        throw e;
    }

} // end of init



/**
 * @param request
 * @return
 * @throws JMSException
 */
private String sendRequest( String request ) throws JMSException
{

    // Create JMS objects
    Destination destination = session.createQueue( "queue:///" + writeQueueName );

    // Enable write of MQMD fields. See documentation for further
    // details.
    ((JmsDestination) destination).setBooleanProperty( WMQConstants.WMQ_MQMD_WRITE_ENABLED, true );

    // Set message context, if needed. See comment at the top.

    // Create a producer
    MessageProducer producer = session.createProducer( destination );

    // Create a message
    TextMessage message = session.createTextMessage( request );

    // Generate a custom message id
    message.setJMSCorrelationID( generateRandomID() );

    // Start the connection
    connection.start();

    // And, send the message
    producer.send( message );
    System.out.println(message);

    return message.getJMSCorrelationID();
}


/**
 * @param customMessageId
 * @return
 * @throws JMSException
 */
private String recvResponse( String customMessageId ) throws JMSException
{
    Destination destination = session.createQueue( "queue:///" + readQueueName );

    // Enable read of MQMD fields.
    ((JmsDestination) destination).setBooleanProperty( WMQConstants.WMQ_MQMD_READ_ENABLED, true );
    ((JmsDestination) destination).setObjectProperty( WMQConstants.JMS_IBM_MQMD_CORRELID, customMessageId );

    // Create a consumer
    MessageConsumer consumer = session.createConsumer( destination );

    // Start the connection
    connection.start();

    // And, receive a message from the queue
    TextMessage receivedMessage = (TextMessage)consumer.receive( 15000 );

    connection.close();
    session.close();

    return receivedMessage.getText();
}

以下是主要方法的片段......

    try
    {
        String customMessageId;
        init();
        customMessageId = sendRequest( request );
        return recvResponse( customMessageId );
    }
    catch( Exception ex )
    {
        System.out.println( "Error on MQ." );
        throw new Exception( "\n\n*** An error occurred ***\n\n" + ex.getLocalizedMessage()
                             + "\n\n**********************************" );
    }

2 个答案:

答案 0 :(得分:3)

QueueReceiver queueReceiver = 
    session.createReceiver(destination, "JMSCorrelationID='customMessageId'");

TextMessage receivedMessage = (TextMessage)queueReceiver.receive( 15000 );

在我的示例中,customMessageId应包含您先前设置的实际值。

此外,我已经看到很多情况,人们生成一个correlationID并在出站消息中设置它,期望能够根据该值选择响应。教科书的方法是让服务提供者应用程序在响应时将消息ID复制到相关ID。请求者仍将JMSCorrelationID指定为选择器,但将使用原始JMSMessageID作为值。由于JMSMessageID保证即使在QMgrs中也是唯一的,因此您很可能不会在此值上发生冲突。您需要确保您的客户端与服务提供商的行为相匹配,以确定将哪个值复制到相关ID中。

答案 1 :(得分:1)

这可能是临时队列的一个用例,它只与创建它的连接相关联。

onJava上有一篇详细文章,Designing Messaging Applications with Temporary Queues

  

“临时目的地(temporary queues或临时主题)是   建议作为轻量级替代品   在可扩展的系统架构中   可以用作唯一目的地   回复。这样的目的地有一个   范围仅限于连接   创建它,并删除   服务器端尽快连接   已关闭。“

和Java文档解释:

  

您可以使用临时目的地   实现简单的请求/回复   机制。如果你创建一个临时的   目的地并将其指定为   JMSReplyTo消息头的值   发送邮件的字段,   消息的消费者可以使用   JMSReplyTo字段的值为   它发送回复的目的地   并且还可以参考原文   通过设置请求   JMSCorrelationID头部字段   回复消息的值   JMSMessageID的头字段   请求。