簡體   English   中英

更新:IBM MQ 系列上的 Spring 引導 JMS static 回復隊列

[英]Update: Spring Boot JMS static reply queue on IBM MQ Series

在我的用例中,我需要通過托管隊列對遠程系統進行請求-回復調用。 使用 Spring Boot 和 IBM 的 MQ 啟動器,我遇到的問題是應用程序想要創建動態/臨時回復隊列,而不是使用已經存在的托管隊列。

配置在這里設置

@EnableJms
@Configuration
public class QueueConfiguration {

  @Bean
  public MQQueueConnectionFactory connectionFactory() throws JMSException {
    MQQueueConnectionFactory factory = new MQQueueConnectionFactory();
    factory.setTransportType(CT_WMQ);                  // is 1
    factory.setHostName(queueProperties.getHost());
    factory.setPort(queueProperties.getPort());
    factory.setChannel(queueProperties.getChannel());  // combo of ${queueManager}%${channel}
    return factory;
  }

  @Bean
  public JmsMessagingTemplate messagingTemplate(ConnectionFactory connectionFactory) {
    JmsMessagingTemplate jmt = new JmsMessagingTemplate(connectionFactory);
    jmt.setDefaultDestinationName(queueProperties.getQueueName());
    return jmt;
  }

  @Bean
  public Jaxb2Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setPackagesToScan("com.foo.model");
    return marshaller;
  }

  @Bean
  public MessageConverter messageConverter(Jaxb2Marshaller marshaller) {
    MarshallingMessageConverter converter = new MarshallingMessageConverter();
    converter.setMarshaller(marshaller);
    converter.setUnmarshaller(marshaller);
    return converter;
  }
}

用法非常簡單:將 object 轉換並發送。 等待響應接收並轉換它。

@Component
public class ExampleSenderReceiver {

  @Autowired
  private JmsMessagingTemplate jmsMessagingTemplate;

  @Override
  @SneakyThrows
  public ResponseExample sendAndReceive(RequestExample request, String correlationId) {
    MessagePostProcessor mpp = message -> {
      message = MessageBuilder.fromMessage(message)
          .setHeader(JmsHeaders.CORRELATION_ID, correlationId)
          // .setHeader(JmsHeaders.REPLY_TO, "DEV.QUEUE.3") this triggers queue creation
          .build();
      return message;
    };
    String destination = Objects.requireNonNull(jmsMessagingTemplate.getDefaultDestinationName());
    return jmsMessagingTemplate.convertSendAndReceive(destination, request, ResponseExample.class, mpp);
  }

我已經閱讀了很多 IBM 文檔並認為,我需要將消息類型設置為“MQMT_REQUEST”,但我沒有找到合適的位置。

更新

添加了Gary 建議的 Spring 集成並添加了 JmsOutboundGateway 的配置

  @Bean
  public MessageChannel requestChannel() {
    return new DirectChannel();
  }

  @Bean
  public QueueChannel responseChannel() {
    return new QueueChannel();
  }

  @Bean
  @ServiceActivator(inputChannel = "requestChannel" )
  public JmsOutboundGateway jmsOutboundGateway( ConnectionFactory connectionFactory) {
    JmsOutboundGateway gateway = new JmsOutboundGateway();
    gateway.setConnectionFactory(connectionFactory);
    gateway.setRequestDestinationName("REQUEST");
    gateway.setReplyDestinationName("RESPONSE");
    gateway.setReplyChannel(responseChannel());
    gateway.setCorrelationKey("JMSCorrelationID*");
    gateway.setIdleReplyContainerTimeout(2, TimeUnit.SECONDS);
    return gateway;
  }

並改編了我的 ExampleSenderReceiver class

 @Autowired
 @Qualifier("requestChannel")
 private MessageChannel requestChannel;
   
 @Autowired
 @Qualifier("responseChannel")
 private QueueChannel responseChannel;

 @Override
 @SneakyThrows
 public ResponseExample sendAndReceive(RequestExample request, String correlationId) {
   String xmlContent = "the marshalled request object";   

   Map<String, Object> header = new HashMap<>();
   header.put(JmsHeaders.CORRELATION_ID, correlationId);

   GenericMessage<String> message1 = new GenericMessage<>(xmlContent, header);
   requestChannel.send(message1);
   log.info("send done" );

   Message<?> receive = responseChannel.receive(1500);
   if(null != receive){
     log.info("incoming: {}", receive.toString());
   }
 }

重要的部分是gateway.setCorrelationKey("JMSCorrelationID*");

沒有那條線,correlationId 沒有正確傳播。

下一步是重新添加 MessageConverters 並讓它再次變得更好。

謝謝你。

默認的 JmsTemplate(由JmsMessagingTemplate使用)始終使用臨時回復隊列。 您可以對其進行子類化並覆蓋doSendAndReceive(Session session, Destination destination, MessageCreator messageCreator)以使用您的托管隊列。

但是,它僅在您一次有一個未完成的請求時才有效(例如,所有請求都在單個線程上運行)。 您還必須通過檢查相關 id 添加用於丟棄“遲到”到達的代碼。

您可以改用異步發送並處理偵聽器容器上的回復並將回復與請求相關聯。

考慮改用spring-integration-jms及其出站網關 - 它在回復隊列處理方面具有更大的靈活性(並為您完成所有相關性)。

https://docs.spring.io/spring-integration/reference/html/jms.html#jms-outbound-gateway

您缺少隊列管理器。

ibm:
  mq:
    queueManager: QM1
    channel: chanel
    connName: localhost(1414)
    user: admin
    password: admin

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM