rabbitosgi

Utilities for using RabbitMQ in OSGi

Stars
16

RabbitOSGi - Utilities for RabbitMQ in OSGi

This project has been created to explore ways of using the RabbitMQ messaging broker from OSGi, in particular how we can integrate with the Service Registry to get ESB-like functionality.

Running Equinox

To launch Equinox, type the following command:

java -jar runtime/equinox.jar -console

We are using the FileInstall bundle from Peter Kriens (http://www.aqute.biz/Code/FileInstall). Any valid bundles copied into the load directory will be automatically installed and started. It should not be necessary to restart Equinox during development and testing.

Building Bundles

To build all bundles, simply run ant. Bundles are generated in the load directory so that they are automatically installed in the running Equinox instance.

To build an individual bundle, the Bnd tool (also by Peter Kriens, http://www.aqute.biz/Code/Bnd) can be used as follows:

bnd build -eclipse .. commands.bnd

This style of the command uses the presence of an Eclipse project in the parent directory in order to calculate a classpath. You can also use an explicit classpath as follows:

bnd build -classpath ../classes commands.bnd

Note that "bnd" is assumed to be an alias for java -jar bnd.jar.

If you are developing in Eclipse and have Bnd installed as an Eclipse plug-in, individual bundles can be built simply by right-clicking on the .bnd file and selecting Make Bundle. See the Bnd documentation for instructions on installing as an Eclipse plug-in.

Connections Bundle

The "connections" bundle registers a ManagedServiceFactory (MSF) as defined by the OSGi Configuration Admin specification. This allows us to create connections declaratively using Configuration records. We can use this MSF in conjunction with the FileInstall bundle, which creates Configuration records based on properties files it finds in the load directory.

To connect to a RabbitMQ broker on localhost with the default username, password and virtual host, create a file in the load directory named rabbitmq.connections-localhost.cfg with the following content:

name=mycon
host=localhost
username=guest
password=guest
vhost=/

Additional connections can be created in the same way by using a different suffix after the hyphen in the filename.

Exchanges Bundle

This bundle adds a declarative way to create AMQP exchanges for a particular connection, using Config Admin. To declare an exchange named FooEx on the local connection, create a file named rabbitmq.exchanges-fooex.cfg in the load directory with the following content:

connection.name=local
exchange.name=FooEx
exchange.type=direct        #optional, defaults to "direct"
exchange.passive=false      #optional, defaults to false
exchange.durable=false      #optional, defaults to false
exchange.autoDelete=false   #optional, defaults to false

This will cause a service of type Exchange to be registered in the Service Registry. Exchange is an interface that simply offers the basicPublish method. This allows clients that want to simply send a message in "fire and forget" mode to quickly obtain a pre-declared exchange and publish to it without going through the hassle of opening a connection and creating a channel.

Consumer Bundle

This bundle watches for connection instances published in the Service Registry and creates a simple consumer for each one. The consumer receives messages from the "FooQueue" queue and simply prints them to the console.

TODO: explore how to make this more declarative and POJO-based.

Commands Bundle

This bundle provides commands into the OSGi console for manual control over the RabbitMQ broker. Note that it runs only under Equinox, since extending the console uses a framework-specific API (the other bundles will work under any OSGi R4 framework).

The commands provided are as follows:

* listConns: List connected channels.
* declExchange: Declare an exchange on the specified broker connection.
* declQ: Declare a queue.
* bindQ: Bind a queue to an exchange.
* publish: Publish a message to an exchange.
* receive: Retrieve a single message from a queue and print it.

Example Usage

After building the bundles, the following sequence of commands can be used to test sending and receiving messages:

osgi> listConns
{mycon}={connection.host=localhost}
    Registered by bundle: channel 0

osgi> declExchange mycon FooEx direct
Exchange Declared

osgi> declQ mycon FooQueue
Queue Declared

osgi> bindQ mycon FooQueue FooEx FooQueue
Queue Bound

osgi> publish mycon FooEx FooQueue "Hello World"
Message Published

osgi> ---Message Received---
Hello World

Notes on "OSGifying" the RabbitMQ Client Library

In order to use the RabbitMQ client library under OSGi it must be transformed into an OSGi bundle. This process (sometimes called "bundleizing" or "OSGifying") involves introspecting the bytecode contained in the library and generating the necessary dependency declarations to be placed in the MANIFEST.MF. It must also be done for the Apache Commons IO library on which RabbitMQ depends.

Bnd is able to OSGify libraries but it must be provided certain information such as the name and version of the new bundle. This information is provided by two files in the original subdirectory: com.rabbitmq.client_1.5.0.beta.bnd and org.apache.commons.io_1.2.0.bnd. To generate the bundles we can simply run Bnd as follows:

bnd com.rabbitmq.client_1.5.0.beta.bnd
bnd org.apache.commons.io_1.2.0.bnd

The resulting bundle JARs can still be used as ordinary JAR files in traditional non-OSGi Java environments. It would be advantageous therefore to incorporate this step into the main build for the RabbitMQ client library.

Licence

Copyright (c) 2009 Neil Bartlett. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html