Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更新:IBM MQ系列上的Spring Boot JMS静态回复队列_Java_Spring Boot_Spring Integration_Ibm Mq_Spring Jms - Fatal编程技术网

Java 更新:IBM MQ系列上的Spring Boot JMS静态回复队列

Java 更新:IBM MQ系列上的Spring Boot JMS静态回复队列,java,spring-boot,spring-integration,ibm-mq,spring-jms,Java,Spring Boot,Spring Integration,Ibm Mq,Spring Jms,在我的用例中,我需要通过托管队列对远程系统进行请求-应答呼叫。使用springboot和IBM的mqstarter,我遇到了一个问题:应用程序希望创建动态/临时应答队列,而不是使用已经存在的托管队列 配置是在这里设置的 @EnableJms @Configuration public class QueueConfiguration { @Bean public MQQueueConnectionFactory connectionFactory() throws JMSExcepti

在我的用例中,我需要通过托管队列对远程系统进行请求-应答呼叫。使用springboot和IBM的mqstarter,我遇到了一个问题:应用程序希望创建动态/临时应答队列,而不是使用已经存在的托管队列

配置是在这里设置的

@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;
  }
}
用法非常简单:将对象转换并发送。等待响应接收 并转换它

@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_请求”,但我没有找到正确的位置

更新 添加了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;
  }
并改编了我的示例SenderReceiver类

 @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());
   }
 }
@Autowired
@限定符(“请求通道”)
私有消息通道请求通道;
@自动连线
@限定符(“响应通道”)
专用队列通道响应通道;
@凌驾
@鬼鬼祟祟
公共响应示例发送和接收(请求示例请求,字符串关联ID){
String xmlContent=“已封送的请求对象”;
Map header=newhashmap();
header.put(JmsHeaders.CORRELATION_ID,correlationId);
GenericMessage1=新的GenericMessage(xmlContent,标头);
requestChannel.send(message1);
日志信息(“发送完成”);
消息接收=响应通道接收(1500);
如果(null!=接收){
log.info(“传入:{}”,receive.toString());
}
}
重要的部分是gateway.setCorrelationKey(“JMSCorrelationID*”)

没有该行,correlationId的传播就不正确

下一步是重新添加MessageConverters并使其再次变得漂亮


谢谢。

您缺少队列管理器

ibm:
  mq:
    queueManager: QM1
    channel: chanel
    connName: localhost(1414)
    user: admin
    password: admin
默认JmsTemplate(由
jmsMessageTemplate
使用)始终使用临时应答队列。您可以将其子类化并覆盖
dosendandereceive(会话会话、目标、MessageCreator MessageCreator)
以使用托管队列

但是,只有在一次有一个未完成的请求(例如,所有请求都在一个线程上运行)时,它才会起作用。您还必须通过检查相关id来添加丢弃“延迟”到达的代码

您可以改为使用异步发送,在侦听器容器上处理回复,并将回复与请求关联起来

考虑改用
springintegrationjms
及其出站网关-它在应答队列处理方面具有更大的灵活性(并为您提供所有相关功能)


队列管理器是通道属性的一部分,我在后面的注释中写了它。另一种方法是在jmsTemplate上使用
send
,而不是
send和receive
。记住在发送邮件时将REPLY_设置为。然后,您可以在回复队列上设置一个常规的
侦听器
。这是另一个最初的想法,但随后需要缓存调用的上下文,并且必须手动关联响应。还需要只收集属于请求的响应,因此网关的动态消息选择器非常适合这个用例。我想您可能需要使用消息头。请求添加消息头设置,响应者将消息头设置添加到回复中,侦听器在消息头设置上使用选择器。