Как сопоставить ответные сообщения MQ Server с правильным запросом - PullRequest
4 голосов
/ 16 февраля 2011

Я подключаюсь к IBM Websphere MQ. Я хочу иметь возможность сопоставить ответное сообщение с правильным сообщением запроса. Я пролистал сотни страниц, чтобы получить это, и мне не повезло.

У меня есть класс MQHandler, который отправляет сообщение в одну определенную очередь и читает запрос из другой. Однако это работает нормально, если приложение одновременно используют несколько пользователей, сообщения перепутаны.

Кажется, я не могу получить метод на приемнике, чтобы указать соответствующий идентификатор CorrelationID. Что-то вроде ...

customer.receive (селектор);

Можете ли вы проверить приведенные ниже методы, чтобы убедиться, что я делаю это правильно?

/**
 * 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 ]

3 голосов
/ 16 февраля 2011
QueueReceiver queueReceiver = 
    session.createReceiver(destination, "JMSCorrelationID='customMessageId'");

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

В моем примере customMessageId должен содержать фактическое значение, которое вы ранее установили.

Кроме того, я видел много случаев, когда люди генерировали ID корреляции и устанавливали его в исходящем сообщении, ожидая, что смогут выбрать ответ на основе этого значения.Учебное пособие для этого состоит в том, чтобы приложение поставщика услуг при ответе копировало идентификатор сообщения в идентификатор корреляции.Запрашивающая сторона по-прежнему будет указывать JMSCorrelationID в качестве селектора, но будет использовать исходный JMSMessageID в качестве значения.Так как JMSMessageID гарантированно будет уникальным даже для QMgrs, вы с гораздо меньшей вероятностью столкнетесь с этим значением.Вам необходимо убедиться, что ваш клиент соответствует поведению поставщика услуг, в отношении которого значение копируется в идентификатор корреляции.

1 голос
/ 05 марта 2011

Это может быть случай использования временной очереди, которая связана только с соединением, которое ее создает.

Подробная статья на onJava, Разработка приложений обмена сообщениями с временными очередями

«Временные пункты назначения ( временные очереди или временные разделы) предлагаются в качестве упрощенной альтернативы в архитектуре масштабируемой системы, которая может использоваться в качестве уникальных пунктов назначения для ответов.Такие места назначения имеют область действия, ограниченную соединением, которое его создало, и удаляются на стороне сервера, как только соединение закрывается ».

, а документация по Java объясняет:

Вы можете использовать временные пункты назначения для реализации простого механизма запроса / ответа.Если вы создаете временное место назначения и задаете его в качестве значения поля заголовка сообщения JMSReplyTo при отправке сообщения, получатель сообщения может использовать значение поля JMSReplyTo в качестве места назначения, на которое он отправляет ответ, а также может ссылаться на него.исходный запрос, задав в поле заголовка JMSCorrelationID ответного сообщения значение поля заголовка JMSMessageID запроса.

...