Spring Remoting mit JMS und ActiveMQ

Spring Remoting mit JMS und ActiveMQ

1. Überblick

Wir haben inprevious article gesehen, wieSpring Remoting verwendet werden kann, umRPC über einem asynchronen Kanal alsAMQP-Warteschlange bereitzustellen. Das gleiche Ergebnis können wir jedoch auch mitJMS erzielen.

In diesem Artikel erfahren Sie, wie Sie einen Remote-Aufruf mitSpring Remoting JMS undApache ActiveMQ als Messaging-Middleware einrichten.

2. Starten eines Apache ActiveMQ Broker

Apache ActiveMQ ist einopen source message broker, mit dem Anwendungen Informationen asynchron austauschen können, und es ist vollständig kompatibel mitJava Message ServiceAPI.

Um unser Experiment auszuführen, müssen wir zuerst eine laufende Instanz vonActiveMQ einrichten. Sie können zwischen verschiedenen Möglichkeiten wählen: Befolgen Sie die inofficial guide beschriebenen Schritte, binden Sie sie in eineJava-Anwendung ein oder drehen Sie einfach einenDocker-Container mit dem folgenden Befehl:

docker run -p 61616:61616 -p 8161:8161 rmohr/activemq:5.14.3

Dadurch wird einActiveMQ-Container gestartet, der auf Port 8081 eine einfache Web-GUI für die Verwaltung bereitstellt, über die wir die verfügbaren Warteschlangen, verbundenen Clients und andere Verwaltungsinformationen überprüfen können. JMS Clients müssen Port 61616 verwenden, um eine Verbindung zum Broker herzustellen und stattdessen Nachrichten auszutauschen.

3. Maven-Abhängigkeiten

Wie in den vorherigen Artikeln zuSpring Remoting werden wir einen Server und einen ClientSpring Booteinrichten, um zu zeigen, wieJMS Remoting funktioniert.

Wie gewöhnlich wählen wir die Starterabhängigkeiten vonSpring Bootorgfältig aus,as explained here:


    org.springframework.boot
    spring-boot-starter-activemq
    
        
            org.springframework.boot
            spring-boot-starter-tomcat
        
    

Wir haben diespring-boot-starter-tomcat explizit ausgeschlossen, um dieTomcat-bezogenen.jar-Dateien nicht im Klassenpfad zu haben.

Dies verhindert wiederum, dass der Autokonfigurationsmechanismus vonSpring Bootbeim Start der Anwendung einen eingebetteten Webserver startet, da wir ihn nicht benötigen.

4. Serveranwendung

4.1. Stellen Sie den Service bereit

Wir richten eine Serveranwendung ein, die dieCabBookingService verfügbar macht, die Clients aufrufen können.

The first step is to declare a bean that implements the interface of the service we want to expose to the clients. Dies ist die Bean, die die Geschäftslogik auf dem Server ausführt:

@Bean
CabBookingService bookingService() {
    return new CabBookingServiceImpl();
}

Definieren wir dann die Warteschlange, aus der der Server Aufrufe abruft, und geben den Namen im Konstruktor an:

@Bean
Queue queue() {
    return new ActiveMQQueue("remotingQueue");
}

Wie wir bereits aus den vorherigen Artikeln wissen, istone of the main concepts of Spring Remoting is the Service Exporter, the component that collects the invocation requests from some source, in diesem Fall eineApacheMQ-Warteschlange ─ und ruft die gewünschte Methode für die Service-Implementierung auf.

Um mitJMS zu arbeiten, definieren wirJmsInvokerServiceExporter:

@Bean
JmsInvokerServiceExporter exporter(CabBookingService implementation) {
    JmsInvokerServiceExporter exporter = new JmsInvokerServiceExporter();
    exporter.setServiceInterface(CabBookingService.class);
    exporter.setService(implementation);
    return exporter;
}

Schließlich müssen wir einen Listener definieren, der für das Konsumieren von Nachrichten verantwortlich ist. Daslistener acts as a bridge between ApacheMQ and the*JmsInvokerServiceExporter*,, das die in der Warteschlange verfügbaren Aufrufnachrichten abhört, leitet den Aufruf an den Service-Exporter weiter und serialisiert die Ergebnisse zurück:

@Bean SimpleMessageListenerContainer listener(
  ConnectionFactory factory,
  JmsInvokerServiceExporter exporter) {

    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(factory);
    container.setDestinationName("remotingQueue");
    container.setConcurrentConsumers(1);
    container.setMessageListener(exporter);
    return container;
}

4.2. Aufbau

Denken Sie daran, die Dateiapplication.propertieso einzurichten, dassSpring Booteinige grundlegende Objekte konfigurieren kann, z. B. die vom Listener benötigtenConnectionFactory. Die Werte der verschiedenen Parameter hängen hauptsächlich vom Weg ab

Die Werte der verschiedenen Parameter hängen hauptsächlich von der Art und Weise ab, wieApacheMQ installiert wurde. Die folgende Konfiguration ist eine sinnvolle Konfiguration für unserenDocker-Container, der auf demselben Computer ausgeführt wird, auf dem diese Beispiele ausgeführt werden:

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.packages.trusted=org.springframework.remoting.support,java.lang,com.example.api

Der Parameterspring.activemq.broker-url verweist auf den PortAMQ. Eine tiefere Erklärung ist stattdessen fürspring.activemq.packages.trusted parameter erforderlich. Seit Version 5.12.2 lehnt ActiveMQ standardmäßig jede Nachricht vom Typ ab

Ab Version 5.12.2 lehnt ActiveMQ standardmäßig alle Nachrichten vom TypObjectMessage ab, die zum Austausch von serialisiertenJava-Objekten verwendet werden, da sie in einigen Kontexten als potenzieller Vektor für einen Sicherheitsangriff angesehen werden.

Auf jeden Fall ist es möglich,AMQ anzuweisen, serialisierte Objekte in bestimmten Paketen zu akzeptieren. org.springframework.remoting.support ist das Paket, das die Hauptnachrichten enthält, die den Aufruf einer Remote-Methode und deren Ergebnis darstellen. Das Paket

Das Paketcom.example.api enthält die Parameter und die Ergebnisse unseres Service. java.lang wird hinzugefügt, da das Objekt, das das Ergebnis der Taxibuchung darstellt, aufString verweist. Daher müssen wir dies auch serialisieren.

5. Client-Anwendung

5.1. Rufen Sie den Remote-Dienst auf

Lassen Sie uns jetzt den Kunden ansprechen. Auch hier müssen wir die Warteschlange definieren, in die die Aufrufnachrichten geschrieben werden. Wir müssen überprüfen, ob sowohl Client als auch Server denselben Namen verwenden.

@Bean
Queue queue() {
    return new ActiveMQQueue("remotingQueue");
}

Wir müssen dann einen Exporteur einrichten:

@Bean
FactoryBean invoker(ConnectionFactory factory, Queue queue) {
    JmsInvokerProxyFactoryBean factoryBean = new JmsInvokerProxyFactoryBean();
    factoryBean.setConnectionFactory(factory);
    factoryBean.setServiceInterface(CabBookingService.class);
    factoryBean.setQueue(queue);
    return factoryBean;
}

Wir können den Remote-Service jetzt so verwenden, als ob er als lokale Bean deklariert wäre:

CabBookingService service = context.getBean(CabBookingService.class);
out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));

5.2. Führen Sie das Beispiel aus

Auch für die Client-Anwendung müssen wir die Werte in der%(t0)s-Datei der Anwendung richtig auswählen. In einer allgemeinen Konfiguration stimmen diese genau mit denen überein, die auf der Serverseite verwendet werden.

Dies sollte ausreichen, um den Remote-Aufruf durchApache AMQ zu demonstrieren. Starten wir also zuerstApacheMQ, dann die Serveranwendung und schließlich die Clientanwendung, die den Remotedienst aufruft.

6. Fazit

In diesem kurzen Tutorial haben wir gesehen, wie wirSpring Remoting verwenden können, umRPC über einemJMS-System alsAMQ bereitzustellen.

Spring Remoting zeigt weiterhin, wie einfach es ist, einen asynchronen Anruf unabhängig vom zugrunde liegenden Kanal schnell einzurichten.

Wie üblich finden Sie die Quellenover on GitHub.