Beliebte Suchanfragen
//

AMQP Messaging mit RabbitMQ und Spring

20.4.2011 | 3 Minuten Lesezeit

RabbitMQ ist als Messaging-System Teil der vFabric Cloud Application Platform. Die Unterstützung des performanten Messaging Protokolls AMQP prädestiniert RabbitMQ für den Einsatz in Hochverfügbarkeitsszenarien. RabbitMQ ist ein Open-Source-Produkt und kann daher auch außerhalb der vFabric Plattform eingesetzt werden. Kommerzieller Support steht bei Bedarf zur Verfügung.

In diesem Artikel soll gezeigt werden, wie Sie mit Hilfe von Spring AMQP einen RabbitMQ-Broker an Ihre Java-Anwendung anbinden können.

Erlang/OTP Installation

RabbitMQ ist in Erlang implementiert. Da Erlang auf einer eigenen Runtime ausgeführt wird, müssen wir zunächst die Erlang-Runtime OTP (Open Telecom Platform) installieren. Wir verwenden den Release R14B02 für die Windows-Plattform. Als Installationsverzeichnis wählen wir C:\erl5.8.3 und definieren eine Umgebungsvariable, die auf dieses Verzeichnis zeigt:

1ERLANG_HOME=C:\erl5.8.3

RabbitMQ Installation

Nach dem Download von RabbitMQ entpacken wir das ZIP nach C:\rabbitmq_server-2.4.1. Gestartet wird RabbitMQ durch den Aufruf des Skripts

1C:\rabbitmq_server-2.4.1\sbin\rabbitmq-server.bat

RabbitMQ Server

RabbitMQ zeichnet sich durch einen geringen initialen Speicherverbrauch aus und ist schnell hochgefahren, was in elastisch skalierenden Cloud-Umgebungen von Vorteil ist. Client-APIs werden für verschiedene Sprachen angeboten, u.a. gibt es APIs für Java und .NET.

Spring AMQP

Mit Spring AMQP steht ein komfortables API zur Verfügung, um auf AMQP-fähige Message-Broker zugreifen zu können. Wie üblich gibt es ein Template als zentralen Zugriffspunkt. In unserem Fall das AmqpTemplate.

Die Abhängigkeiten zwischen den wesentlichen benötigten Spring-Projekten sind in der folgenden Abbildung dargestellt:

Spring AMQP API

Das Projekt spring-amqp enthält im Wesentlichen allgemeine Interfaces (z.b. das AmqpTemplate) und Schnittstellenklassen, während in spring-rabbitmq Broker-spezifische Implementierungen liegen. spring-rabbitmq stützt sich dabei auf die allg. Java API für RabbitMQ amqp-client.

Ihre Client-Anwendung hängt idealerweise nur von spring-amqp ab, so dass eine lose Kopplung entsteht und der AMQP-Broker bei Bedarf ausgetauscht werden kann.

Für die folgenden Code-Beispiele wurde diese Maven-Artefakte verwendet:

1...
2<repositories>
3    <repository>
4        <id>repository.springframework.maven.milestone</id>
5        <name>Spring Framework Maven Milestone Repository</name>
6        <url>http://maven.springframework.org/milestone</url>
7    </repository>
8</repositories>
9<properties>
10    <spring.framework.version>3.0.5.RELEASE</spring.framework.version>
11    <spring.amqp.version>1.0.0.M3</spring.amqp.version>
12    <rabbitmq.version>2.2.0</rabbitmq.version>
13</properties>
14<dependencies>
15    <dependency>
16        <groupId>org.springframework</groupId>
17        <artifactId>spring-core</artifactId>
18        <version>${spring.framework.version}</version>
19    </dependency>
20    <dependency>
21        <groupId>org.springframework.amqp</groupId>
22        <artifactId>spring-amqp</artifactId>
23        <version>${spring.amqp.version}</version>
24        <exclusions>
25            <exclusion>
26                <groupId>com.sun.jmx</groupId>
27                <artifactId>jmxri</artifactId>
28            </exclusion>
29        </exclusions>
30    </dependency>
31    <dependency>
32        <groupId>org.springframework.amqp</groupId>
33        <artifactId>spring-rabbit</artifactId>
34        <version>${spring.amqp.version}</version>
35    </dependency>
36    <dependency>
37        <groupId>org.springframework.amqp</groupId>
38        <artifactId>spring-erlang</artifactId>
39        <version>${spring.amqp.version}</version>
40    </dependency>
41    <dependency>
42        <groupId>com.rabbitmq</groupId>
43        <artifactId>amqp-client</artifactId>
44        <version>${rabbitmq.version}</version>
45    </dependency>
46    <dependency>
47        <groupId>junit</groupId>
48        <artifactId>junit</artifactId>
49        <version>4.7</version>
50        <scope>test</scope>
51    </dependency>
52    <dependency>
53        <groupId>org.springframework</groupId>
54        <artifactId>spring-test</artifactId>
55        <version>${spring.framework.version}</version>
56        <scope>test</scope>
57    </dependency>
58</dependencies>
59...

AMQP Template

Der Einfachheit halber werden die Code-Beispiele in Form eines JUnit-Tests präsentiert. Im Application Context werden eine Connection Factory und das AmqpTemplate definiert. Zusätzlich spendieren wir noch ein Bean zur Administration des Brokers.

1<!-- Connection Factory -->
2<bean id="rabbitConnFactory" 
3    class="org.springframework.amqp.rabbit.connection.SingleConnectionFactory">
4    <constructor-arg><value>localhost</value></constructor-arg>
5    <property name="username" value="guest" />
6    <property name="password" value="guest" />
7    <property name="virtualHost" value="/" />
8    <property name="port" value="5672" />
9</bean>
10 
11<!-- Spring AMQP Template -->
12<bean id="template" 
13    class="org.springframework.amqp.rabbit.core.RabbitTemplate">
14    <property name="connectionFactory" ref="rabbitConnFactory" />
15    <property name="routingKey" value="test.queue"/>
16    <property name="queue" value="test.queue"/>
17</bean>
18 
19<!-- Spring AMQP Admin -->
20<bean id="admin" class="org.springframework.amqp.rabbit.core.RabbitAdmin">
21    <constructor-arg ref="rabbitConnFactory" />
22</bean>

Die Connection Factory wird im Wesentlichen mit den TCP/IP-Verbindungsdaten zum RabbitMQ Server versorgt. Default-Port nach einer RabbitMQ-Installation ist 5672, als Credentials können guest/guest verwendet werden.

Ein konkretes Template bezieht sich auf eine bestimmte Queue, diese trägt den Namen test.queue.

Im folgenden Beispiel können wir guten Gewissens Autowiring verwenden, da wir genau eine Implementierung konfiguriert haben. Wir lassen uns ein AmqpAdmin und ein AmqpTemplate injizieren:

1@RunWith(SpringJUnit4ClassRunner.class)
2@ContextConfiguration
3public class RabbitMQClientTest {
4 
5    @Autowired private AmqpAdmin admin;
6    @Autowired private AmqpTemplate template;
7 
8    @Test public void simpleProducerConsumerTest() {
9        try {
10            String sent = "Catch the rabbit! " + new Date();
11            admin.declareQueue( new Queue("test.queue") );
12 
13            // write message
14            template.convertAndSend( sent );
15            // read message
16            String received = (String)template.receiveAndConvert();
17 
18            System.out.println( "Msg: " + received );
19            Assert.assertEquals( sent, received );
20 
21        } catch (AmqpException e) {
22            Assert.fail( "Test failed: " + e.getLocalizedMessage() );
23        }
24    }
25}

Der Test verwendet zunächst den AmqpAdmin, um die gewünschte Queue test.queue anzulegen. Diese Operation ist idempotent, d.h. sie legt eine Queue nur dann an, wenn diese noch nicht existiert.

Danach kann mit convertAndSend(...) bequem ein beliebiges Objekt über die Leitung gesendet werden. AMQP kennt intern nur Byte-Arrays als Nachrichtentyp, daher übernimmt das Template automatisch die Konvertierung, sofern kein eigener MessageConverter konfiguriert wird. Für unser Beispiel reichen die Standard-Converter, da sowohl Producer als auch Consumer in Java sind.

Anschließend lesen wir mit receiveAndConvert(...) synchron die nächste Nachricht aus unserer Queue und geben diese aus.

Die AmqpException ist wie üblich eine RuntimeException, müsste also nicht direkt mit try/catch behandelt werden, was wir als gute Tester hier aber dennoch tun.

Zusammenfassung

Wir haben gezeigt, wie wir RabbitMQ und die erforderliche Erlang-Runtime installieren und sind auf die Spring-APIs für AMQP eingegangen. Mit einem kleinen Test haben wir gezeigt, wie man als AMQP Message Producer bzw. Message Consumer agiert.

Beitrag teilen

//

Weitere Artikel in diesem Themenbereich

Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.

//

Gemeinsam bessere Projekte umsetzen.

Wir helfen deinem Unternehmen.

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.