Отправка сообщения amqp в ibm mq

#spring-integration #ibm-mq

#spring-интеграция #ibm-mq

Вопрос:

Попытка передать сообщения из RabbitMQ <int-amqp:inbound-channel-adapter в MQSeries <int-jms:outbound-channel-adapter . Это работает нормально.

На самом деле некоторые производители в MQSeries используют подобные классы IBM JMS :

 MQMessage messageMQ = new MQMessage();
messageMQ.format = "        ";
messageMQ.persistence = 1;
messageMQ.correlationId = MQ_MESSAGE_CORRELATION_ID;
messageMQ.write(message.getMessageData());
MQPutMessageOptions putMessageOption = new MQPutMessageOptions();
putMessageOption.options = 8194;
MQQueue queue = openQueue(destinataire, 8208);
queue.put(messageMQ, putMessageOption);
  

Я попытался использовать transformer между amqp и jms следующим образом :

 <int:transformer id="testTransformer" ref="testTransformerBean" input-channel="fromRabbit"
         method="transform" output-channel="toJms"/>


public MQMessage transform(Message<?> msg) throws Exception {

    MQMessage result = new MQMessage();
    result.format = "        ";
    result.persistence = 1;
    result.correlationId = MQC.MQCI_NONE;

    String test = "message to send ";
    result.write(test.getBytes());
    return resu<
}
  

Какой тип объекта хранится в msg.getPayload()? Как я могу преобразовать его в строковый объект?

Реализуя этот метод, у меня есть исключение, потому что исходящему требуется сообщение JMS, а не com.ibm.mq.MQMessage!

 Cannot convert object of type [com.ibm.mq.MQMessage] to JMS message
  

Правильно ли это?

Или я должен удалить исходящий канал и вместо этого использовать активатор службы со специальным кодом для IBM?

Спасибо за вашу помощь

С уважением

Редактировать после ответа Артема

После конфигурации исходящего jms:

 <bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQConnectionFactory">
    <property name="queueManager" value="${queueManager}" />
    <property name="hostName" value="${hostName}" />
    <property name="port" value="${port}" />
    <property name="channel" value="${channelName}" />
    <property name="transportType" value="1" />
</bean>
<bean id="jmsQueue" class="com.ibm.mq.jms.MQQueue" depends-on="jmsConnectionFactory">
    <property name="baseQueueManagerName" value="${queueManager}" />
    <property name="baseQueueName" value="${queueName}" />
    <property name="targetClient" value="1" />
</bean>
<bean id="jmsConnectionFactory_cred"
    class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
    <property name="targetConnectionFactory" ref="jmsConnectionFactory" />
    <property name="username" value="${user}"/> 
    <property name="password" value="${password}"/> 
</bean> 

<bean id="connectionFactoryCaching"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory" ref="jmsConnectionFactory_cred" />
    <property name="sessionCacheSize" value="${BRIDGE_MQ_OUTBOUND_SESSION_CACHE}" />
</bean>

<bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice" id="requestHandler">
    <property name="trapException" value="false"/>
    <property name="onFailureExpressionString" value="#this"/>
    <property name="failureChannel" ref="processChannel1"/>
</bean>

<int-jms:outbound-channel-adapter   channel="channelRmqMQ" 
                                    id="jmsOut" destination="jmsQueue" connection-factory="connectionFactoryCaching" delivery-persistent="true" 
                                    explicit-qos-enabled="true" session-transacted="true" >
    <int-jms:request-handler-advice-chain>
        <ref bean="requestHandler" />
    </int-jms:request-handler-advice-chain>                                         
</int-jms:outbound-channel-adapter>
  

Комментарии:

1. Это не код MQ JMS. Он использует классы Java MQ — более прямое представление базового MQI.

2. Что вы пытаетесь сделать в своем transform методе? Вы пытаетесь создать сообщение JMS? Если это так, то не должно ли оно возвращать что-то похожее javax.jms.message на то, что должно быть создано с помощью метода create для javax.jms.JMSContext объекта?

3. Я пытаюсь преобразовать сообщение в MQMessage. Мне нужно использовать этот класс, потому что для сообщения, используемого потребителями, задано некоторое свойство (например, определенное в моем вопросе). Как можно преобразовать полезную нагрузку (поступающую из amqp Rabbitmq) в строку? Спасибо за помощь

Ответ №1:

Если ваше сообщение AMQP поставляется с text/* contentType , то его тело автоматически преобразуется в строку с помощью готового SimpleMessageConverter в AmqpInboundChannelAdapter :

      if (contentType != null amp;amp; contentType.startsWith("text")) {
            String encoding = properties.getContentEncoding();
            if (encoding == null) {
                encoding = this.defaultCharset;
            }

            try {
                content = new String(message.getBody(), encoding);
            } catch (UnsupportedEncodingException var8) {
                throw new MessageConversionException("failed to convert text-based Message content", var8);
            }
  

В противном случае вам нужно поместить простой преобразователь между ними, чтобы преобразовать a byte[] в string:

 <object-to-string-transformer>
  

Это как <int-jms:outbound-channel-adapter> раз для взаимодействия с протоколом JMS, поэтому ваше MQMessage сообщение там не будет принято. Вот почему вы получаете это Cannot convert object of type [com.ibm.mq.MQMessage] to JMS message исключение.

Да, вы можете использовать IBM MP API напрямую в некоторых пользовательских service-activator , однако я бы посоветовал взглянуть на JMS to MQ bridge в IBM WebSphere. Затем вам нужно только настроить соответствующую фабрику соединений и использовать ее из <int-jms:outbound-channel-adapter> :

 <jee:jndi-lookup id="jndiMqConnectionFactory" jndi-name="${mqConnectionFactory}"/>

<bean id="jmsQueueConnectionFactory"
          class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
        <property name="targetConnectionFactory" ref="jndiMqConnectionFactory"/>
        <property name="username" value="${mqLogin}"/>
        <property name="password" value="${mqPassword}"/>
    </bean>

<jee:jndi-lookup id="myMqQueue" jndi-name="queue/myMqQueue"/>

<bean id="mqQueueJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="jmsQueueConnectionFactory"/>
    <property name="defaultDestination" ref="myMqQueue"/>
</bean>

<jms:outbound-channel-adapter channel="myMqChannel" jms-template="mqQueueJmsTemplate"/>
  

Комментарии:

1. Получение сообщения в виде строки — это нормально! Я уже использую a <int-jms:outbound-channel-adapter> , и он работает очень хорошо;-) (см. Мое редактирование в вопросе) Предыдущий код JMS отправлял другие свойства, не определенные в стандарте jms, например messageMQ.format = " "; , поэтому я хотел бы выполнить ту же обработку в моем исходящем канале. Есть ли способ сделать это?

2. Попробуйте сопоставить все эти пользовательские свойства с headers использованием header-enricher перед отправкой в <int-jms:outbound-channel-adapter> . Эти DefaultJmsHeaderMapper пользовательские заголовки будут сопоставлены jmsMessage.setObjectProperty() с, и я надеюсь, что они будут переназначены MQMessage на WebSphere уже с помощью JMS bridge.

3. Я попытался использовать обогащатель заголовков и попытаться обновить формат сообщения, например <int:header name="format" expression="'MQSTR '" overwrite="true"/> . Вызывается DefaultJmsHeaderMapper и устанавливается свойство jmsMessage.setObjectProperty(propertyName, value); , но, к сожалению, в моем MQExplorer формат не обновляется. Спасибо за вашу помощь