2016-07-20 21 views
1

Ich bin neu in Spring Integration und neu zu Stack Overflow. Ich bin auf der Suche nach Hilfe beim Verständnis von Spring Integration, da es sich auf ein Anfrage-Antwort-Muster bezieht. Beim Lesen im Internet denke ich, dass ich einen Service Activator verwenden sollte, um diese Art von Anwendungsfall zu ermöglichen.Spring Integration - Request-Reply Implementierung

Ich verwende JMS, um das Senden und Empfangen von XML-basierten Nachrichten zu erleichtern. Unsere Unterstreichungsimplementierung ist IBM Websphere MQ.

Ich benutze auch Spring Boot (Version 1.3.6.RELEASE) und versuche eine reine Annotation-basierte Konfiguration Ansatz zu verwenden (wenn das möglich ist). Ich habe das Internet durchsucht und ein Beispiel gesehen, aber nichts, was ich bisher gesehen habe, hilft mir zu verstehen, wie alles zusammenpasst. Die Frühlingsintegrationsdokumentation ist ausgezeichnet, aber ich kämpfe immer noch damit, wie alle Teile zusammenpassen. Ich entschuldige mich im Voraus, wenn es etwas gibt, das ich vermisst habe. Ich behandle das Posting hier als letzte Alternative. Hier

ist, was ich für meine Konfiguration haben:

package com.daluga.spring.integration.configuration 

import com.ibm.mq.jms.MQConnectionFactory; 
import com.ibm.mq.jms.MQQueue; 
import com.ibm.msg.client.wmq.WMQConstants; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.integration.annotation.InboundChannelAdapter; 
import org.springframework.integration.annotation.IntegrationComponentScan; 
import org.springframework.integration.annotation.Poller; 
import org.springframework.integration.channel.QueueChannel; 
import org.springframework.integration.config.EnableIntegration; 
import org.springframework.jms.annotation.EnableJms; 
import org.springframework.jms.connection.CachingConnectionFactory; 
import org.springframework.jms.core.JmsTemplate; 

import javax.jms.ConnectionFactory; 
import javax.jms.DeliveryMode; 
import javax.jms.Destination; 
import javax.jms.JMSException; 

//import com.ibm.msg.client.services.Trace; 

@Configuration 
public class MQConfiguration { 

    private static final Logger LOGGER = LoggerFactory.getLogger(MQConfiguration.class); 

    @Value("${host-name}") 
    private String hostName; 

    @Value("${port}") 
    private int port; 

    @Value("${channel}") 
    private String channel; 

    @Value("${time-to-live}") 
    private int timeToLive; 

    @Autowired 
    @Qualifier("MQConnectionFactory") 
    ConnectionFactory connectionFactory; 

    @Bean(name = "jmsTemplate") 
    public JmsTemplate provideJmsTemplate() { 
     JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); 
     jmsTemplate.setExplicitQosEnabled(true); 
     jmsTemplate.setTimeToLive(timeToLive); 
     jmsTemplate.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  
     return jmsTemplate; 
    } 

    @Bean(name = "MQConnectionFactory") 
    public ConnectionFactory connectionFactory() { 
     CachingConnectionFactory ccf = new CachingConnectionFactory(); 

     //Trace.setOn(); 

     try { 
      MQConnectionFactory mqcf = new MQConnectionFactory(); 
      mqcf.setHostName(hostName); 
      mqcf.setPort(port); 
      mqcf.setChannel(channel); 
      mqcf.setTransportType(WMQConstants.WMQ_CM_CLIENT); 
      ccf.setTargetConnectionFactory(mqcf); 
      ccf.setSessionCacheSize(2); 
     } catch (JMSException e) { 
      throw new RuntimeException(e); 
     } 

     return ccf; 
    } 

    @Bean(name = "requestQueue") 
    public Destination createRequestQueue() { 

     Destination queue = null; 

     try { 
      queue = new MQQueue("REQUEST.QUEUE"); 
     } catch (JMSException e) { 
      throw new RuntimeException(e); 
     } 

     return queue; 
    } 

    @Bean(name = "replyQueue") 
    public Destination createReplyQueue() { 

     Destination queue = null; 

     try { 
      queue = new MQQueue("REPLY.QUEUE"); 
     } catch (JMSException e) { 
      throw new RuntimeException(e); 
     } 

     return queue; 
    } 

    @Bean(name = "requestChannel") 
    public QueueChannel createRequestChannel() { 

     QueueChannel channel = new QueueChannel(); 

     return channel; 
    } 

    @Bean(name = "replyChannel") 
    public QueueChannel createReplyChannel() { 

     QueueChannel channel = new QueueChannel(); 

     return channel; 
    } 

} 

Und hier ist meine Service-Klasse:

package com.daluga.spring.integration.service 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.integration.annotation.ServiceActivator; 
import org.springframework.stereotype.Service; 


@Service 
public class MyRequestReplyService { 

    private static final Logger LOGGER = LoggerFactory.getLogger(MyRequestReplyService.class); 

    @ServiceActivator(inputChannel = "replyChannel") 
    public void sendAndReceive(String requestPayload) { 
     // How to get replyPayload 
    } 

} 

Also, an dieser Stelle, ich bin nicht ganz sicher, wie das alles zu kleben zusammen, um diese Arbeit zu machen. Ich verstehe nicht, wie ich meine Anfrage und die Warteschlangen an den Service-Aktivator klebe, damit alles funktioniert.

Der Dienst, den ich anrufe (basiert auf JMS/Webshere MQ), verwendet die typische Nachrichten- und Korrelations-ID, sodass ich die Anforderung ordnungsgemäß an die entsprechende Antwort binden kann.

Kann mir jemand irgendeine Anleitung geben, wie man das zur Arbeit bringt? Bitte lassen Sie mich wissen, welche zusätzlichen Informationen ich zur Verfügung stellen kann, um dies deutlich zu machen.

Vielen Dank im Voraus für Ihre Hilfe!

Dan

Antwort

1

Gateways bieten Semantik für die Anforderung/Antwort.

Anstatt eine JmsTemplate direkt zu verwenden, sollten Sie Spring Integration's built-in JMS Support verwenden.

@Bean 
@ServiceActivator(inputChannel="requestChannel") 
public MessageHandler jmsOutGateway() { 
    JmsOutboundGateway outGateway = new JmsOutboundGateway(); 
    // set properties 
    outGateway.setOutputChannel(replyChannel()); 
    return outGateway; 
} 

Wenn Sie Ihre eigene Rolle, die Service-Aktivator-Methode der Rückkehr einen Antworttyp und einer der Vorlage sendAndReceive() oder convertSendAndReceive() Methoden ändern.

Die sample app verwendet XML-Konfiguration, sollte jedoch einige zusätzliche Anleitung bieten.

+0

Danke, Gary! Das hat geholfen. Ich trat einen Schritt zurück und entschied mich für die xml-basierte Konfiguration. Ich habe die eingehenden und ausgehenden Gateways konfiguriert und kann sehen, dass Message Consumer in meiner Antwortwarteschlange erstellt wird. Es gibt keine Fehler beim Start. Ich bin in der Lage, eine Nachricht in die Antwortwarteschlange (mit einem JMS-Dienstprogramm) zu stellen und es abholen zu sehen. Was ich aber noch nicht verstehe, ist, wie man den Aufruf der Request-Queue über den Service Activator einleitet. Ich habe eine Klasse erstellt und mit MessageEndpoint und einer Methode für diese Klasse mit ServiceActivator versehen. Ich rufe es dann über die Hauptmethode auf. –

+1

Ändern Sie 'requestChannel()' in einen 'DirectChannel' und senden Sie eine' Nachricht 'an sie - entweder direkt oder über ein [Messaging Gateway] (http://docs.spring.io/spring-integration/reference/html) /messaging-endpoints-chapter.html#gateway).Im Allgemeinen empfehlen wir Letzteres, anstatt den Benutzercode direkt mit der Messaging-Infrastruktur zu interagieren. Sehen Sie sich die Beispiel-Apps für Beispiele an. –

+0

Gary, danke für deine Führung! Ich konnte es alles verdrahten und arbeiten. Sobald du verstehst, was vor sich geht, ist es ziemlich einfach, eins davon zu verkabeln. Pass auf dich auf, Dan. –