(Quick Reference)

7 Advanced Usage - Reference Documentation

Authors: Bud Byrd

Version: 3.1.3

7 Advanced Usage

While the plugin effectively wraps the functionality of the RabbitMQ library, the end user has direct access to all of the underlying library objects and connection instances.

7.1 Spring Beans

The are several beans defined by the plugin to perform its various operations.

Bean NamePurpose
rabbitContextA front-end class to the plugin that aggregates useful functionality for users of the plugin. Besides the rabbitMessagePublisher, this is likely the only bean users will need to access, if at all.
connectionManagerManages the lifecycle of connection instances, including loading, starting, stopping, unloading, and retrieval.
messageConverterManagerHandles loading message converters and acts as the entry point when message conversion is required.
consumerManagerManages the lifecycle of consumer instances, including loading, starting, stopping, unloading, and retrieval.
queueBuilderResponsible for creating exchanges and queues defined in the application's configuration.
rabbitMessagePublisherUsed to send messages to a RabbitMQ broker.

7.2 Rabbit Context

Besides the rabbitMessagePublisher, the rabbitContext is the bean users will most likely interact with. While you may never need to use this bean, it can be useful. As with any Spring bean, the rabbitContext can be injected into any Spring managed bean, such as services, controllers, and rabbit consumers.

The rabbitContext is intended to be used as a front-end to all of the other beans defined by the plugin to hide some of the complexity of interacting with the system. As such, in most cases the rabbitContext proxies requests to the appropriate manager bean to accomplish the requested task.

In some cases, interactions with multiple managers are necessary to safely carry out the action. Therefore, unless the rabbitContext does not provide the required functionality, it should be considered best-practice to use the rabbitContext instead of the other beans directly. If you find that you are frequently resorting to using one of the other beans, I encourage you to post an issue on the GitHub project.

The follow subsections describe some of the more useful functionality the rabbitContext provides.

7.2.1 Native Objects

The main goal of the plugin is to effectively wrap the RabbitMQ library to hide the complexity of its usage and make using it more inline with the conventions of Grails applications, but also allow users to gain access to the underlying RabbitMQ objects if needed. rabbitContext provides several methods to gain direct access to the RabbitMQ Java library Connection and Channel objects.

To create a new Channel, use the createChannel methods.

// This creates a new channel with the default connection
Channel channel = rabbitContext.createChannel()

// The same using a different connection based on its name Channel channel = rabbitContext.createChannel("connection1")

If the createChannel methods are used, it is important that these channels are closed. The plugin handles opening and closing channels that it manages as part of publishing or consuming messages, but channels created with the createChannel methods are not managed by the plugin. It is the author's responsibility to close them, or connection leaks may and memory leaks most likely will occur.

Use the getConnection methods to gain access to the Connection objects.

// To retrieve the Connection from the default connection
Connection connection = rabbitContext.getConnection()

// To retrieve the Connection from a specific connection based on its name Connection connection = rabbitContext.getConnection("connection1")

7.2.2 Starting and Stopping Connections

The plugin handles starting and stopping connections automatically when the application is started or shut down, but sometimes applications may need to manually stop connections based on certain conditions or business logic. The rabbitContext contains several methods to manage the life cycle of connections.

MethodDescription
startConnectionsStarts all registered connections. If some connections are already started, the remainder will also be started.
stopConnectionsStops all connections and all consumers.
startConnectionStarts a connection based on its name.
stopConnectionStops a connection based on its name, and stops any consumers on the connection.

7.2.3 Starting and Stopping Consumers

Much like connections, the rabbitContext provides several methods to start and stop consumers if necessary.

MethodDescription
startConsumersStarts all registered consumers. If some consumers are already started, the remainder will also be started.
stopConsumersStops all consumers.
startConsumerStarts a connection based on its class name.
stopConsumerStops a connection based on its class name.
startConsumers(String)Starts all consumers on a specific connection, based on the connection name.
stopConsumers(String)Stops all consumers on a specific connection, based on the connection name.

7.2.4 Status Report

The RabbitContext contains a method getStatusReport(), which will build an object structure containing information about all RabbitMQ connections and all consumers. This information is useful to monitor the status of the RabbitMQ application system, as it contains running states and statistics including how many concurrent threads a consumer is configured for, how many are actually active, and how many are actively processing messages. Below is an example of its output gathered from one of the plugin's tests, serialized as JSON.

[
    {
        "consumers": [
            {
                "fullName": "com.budjb.rabbitmq.test.AllTopicConsumer",
                "load": 0,
                "name": "AllTopicConsumer",
                "numConfigured": 1,
                "numConsuming": 1,
                "numProcessing": 0,
                "queue": "topic-queue-all",
                "runningState": "RUNNING"
            },
            {
                "fullName": "com.budjb.rabbitmq.test.ReportingConsumer",
                "load": 0,
                "name": "ReportingConsumer",
                "numConfigured": 1,
                "numConsuming": 1,
                "numProcessing": 0,
                "queue": "reporting",
                "runningState": "RUNNING"
            },
            {
                "fullName": "com.budjb.rabbitmq.test.SleepingConsumer",
                "load": 0,
                "name": "SleepingConsumer",
                "numConfigured": 1,
                "numConsuming": 1,
                "numProcessing": 0,
                "queue": "sleeping",
                "runningState": "RUNNING"
            },
            {
                "fullName": "com.budjb.rabbitmq.test.SpecificTopicConsumer",
                "load": 0,
                "name": "SpecificTopicConsumer",
                "numConfigured": 1,
                "numConsuming": 1,
                "numProcessing": 0,
                "queue": "topic-queue-specific",
                "runningState": "RUNNING"
            },
            {
                "fullName": "com.budjb.rabbitmq.test.StringConsumer",
                "load": 0,
                "name": "StringConsumer",
                "numConfigured": 1,
                "numConsuming": 1,
                "numProcessing": 0,
                "queue": "string-test",
                "runningState": "RUNNING"
            },
            {
                "fullName": "com.budjb.rabbitmq.test.SubsetTopicConsumer",
                "load": 0,
                "name": "SubsetTopicConsumer",
                "numConfigured": 1,
                "numConsuming": 1,
                "numProcessing": 0,
                "queue": "topic-queue-subset",
                "runningState": "RUNNING"
            }
        ],
        "host": "localhost",
        "name": "connection1",
        "port": 5672,
        "runningState": "RUNNING",
        "virtualHost": "test1.rabbitmq.budjb.com"
    },
    {
        "consumers": [
            {
                "fullName": "com.budjb.rabbitmq.test.Connection2Consumer",
                "load": 0,
                "name": "Connection2Consumer",
                "numConfigured": 1,
                "numConsuming": 1,
                "numProcessing": 0,
                "queue": "connection2-queue",
                "runningState": "RUNNING"
            }
        ],
        "host": "localhost",
        "name": "connection2",
        "port": 5672,
        "runningState": "RUNNING",
        "virtualHost": "test2.rabbitmq.budjb.com"
    }
]

7.3 Transactions

The plugin provides a bit of automation around channel transactions. When a consumer is defined with the transacted property set to true, a transaction is automatically started on the channel passed to the message handler. When the message handler completes successfully, the transaction is automatically committed. If an unhandled exception is thrown from the message handler, the transaction is automatically rolled back.

It is especially important that any messages published from a message handler use the Channel instance passed in the MessageContext for this functionality to work.

Since the Channel is passed in the MessageContext, the author has full control over committing and rolling back transactions.