RabbitMQ MATLAB Interface

Installation

Building the Java package

Refer to the Getting Started Section in README.md for instructions on building the required JAR-file.

Configuring MATLABPATH and Java class path startup.m

Before using the package in MATLAB, the Java client library needs to be loaded on the MATLAB Java class path and the Software/MATLAB/app directory needs to be added to the MATLABPATH. This can be accomplished by running the startup function from the Software/MATLAB directory.

Note that this will load the JAR-file on the dynamic class path. Not all functionality is supported when the JAR-file is loaded on the dynamic class path, see below. See the MATLAB documentation to learn more about the Java class path in general and on how to add the JAR-file to the static class path if desired/needed.

Usage

Connection Properties

When working with rabbitmq.Producer and rabbitmq.Consumer in MATLAB, various connection properties need to be specified. These can be specified with the help of the rabbitmq.ConnectorProperties class or using YAML configuration files.

rabbitmq.ConnectorProperties class

rabbitmq.ConnectorProperties has various properties:

host

Hostname or IP of the RabbitMQ Server.
Default: "localhost"

port

Port the RabbitMQ Server runs on.
Default: 5672

virtualhost

RabbitMQ Virtual Host.
Default: "/"

exchange

Exchange to work with on RabbitMQ.
Default: Default rabbitmq.ExchangeProperties

queue

Queue to work with on RabbitMQ Server.
Default: Default rabbitmq.QueueProperties

credentials

RabbitMQ server credentials.
Default: Default rabbitmq.Credentials

routingkey

Routing key to subscribe to or poll on - only used for Consumer, when working with Producer the routing key is specified on a per message basis when publishing a message.
Default: "test-topic"

Where, as can be seen, properties exchange, queue and credentials are in turn other MATLAB classes:

rabbitmq.ExchangeProperties

name

Name of the exchange.
Default: "amq.topic"

type

Type of exchange.
Default: "topic"

create

See the note on create in MessageBroker.
Default: true

durable

Only relevant if create = true, create a durable exchange or not
Default: true

autoDelete

Only relevant if create = true, create an autoDelete exchange or not
Default: false

internal

Only relevant if create = true, create an internal exchange or not
Default: false

arguments

Only relevant if create = true, allows setting additional arguments. Use the put method to add additional arguments.
Default: Empty HashMap

rabbitmq.QueueProperties

name

Name of the queue.
Default: "RabbitMQ"

create

See See the note on create in MessageBroker.
Default: true

durable

Only relevant if create = true, create a durable queue or not.
Default: false

exclusive

Only relevant if create = true, create an exclusive queue or not.
Default: false

autoDelete

Only relevant if create = true, create an autoDelete queue or not.
Default: false

arguments

Only relevant if create = true, allows setting additional arguments. Use the put method to add additional arguments.
Default: Empty HashMap

rabbitmq.Credentials

username

Username
Default: "guest"

password

Password
Default: "guest"

Setting properties values can be done through traditional MATLAB class syntax:

% Create an instance
c  = rabbitmq.ConnectorProperties;
% Set a property value
c.host = "myHost";
% Set a property of one of the "nested" settings
c.queue.name = "myQueue";

But (with the exception of the arguments property) they can also be set by providing Name-Value pairs corresponding to property name and the value it is to be set to as inputs to the constructor.

% Create instance and immediately set host to myHost and port to 1234
c  = rabbitmq.ConnectorProperties("host","myHost","port",1234);

To immediately set “nested” settings, use the same trick on one of the nested classes:

% Create the QueueProperties with name and durable set
qp = rabbitmq.QueueProperties("name","myQueue","durable",true);
% Create ConnectorProperties with these QueueProperties set
c  = rabbitmq.ConnectorProperties("queue",qp);

% Or this could even be done one big single call then
c = rabbitmq.ConnectorProperties("queue", ...
    rabbitmq.QueueProperties("name","myQueue","durable",true));

To add additional arguments through the arguments property, use the put method:

% Create QueueProperties with some properties already set
c = rabbitmq.ConnectorProperties("queue", ...
    rabbitmq.QueueProperties("name","myQueue","durable",true));
% Then in a separate step add additional arguments, for example
c.queue.arguments.put('x-max-length',42);
% Similarly for exchange
c.exchange.arguments.put('alternate-exchange', 'my-ea');

Configuration Files

The configuration file follows the same RabbitMQ related options as the configuration file for the MATLAB Production Server interface:

# Messaging connection and routing properties
messageQueue:
  queue:
    name: RabbitMQ          # Name of the Queue on RabbitMQ Server
    create: true            # Creates/verifies whether queue exists
    durable: false          # Work with a durable queue or not
    exclusive: false        # Work with an exclusive queue or not
    autoDelete: false       # Work with an auto delete queue or not
    arguments:              # Set additional arguments, can be omitted entirely
      x-max-length: 42      # For example, set the maximum queue length
  host: localhost           # Hostname or IP of the RabbitMQ Server
  port: 5672                # Port the RabbitMQ Server runs on
  virtualhost: /            # RabbitMQ Virtual Host
  credentials: 
    username: guest         # RabbitMQ username
    password: guest         # RabbitMQ password
  exchange:
    name: amq.topic         # Exchange to work with on RabbitMQ
    create: true            # Creates/verifies whether exchange exists
    durable: true           # Work with a durable exchange or not
    autoDelete: false       # Work with an auto delete exchange or not
    internal: false         # Work with an internal exchange or not
    arguments:              # Set additional arguments, can be omitted entirely
      alternate-exchange: my-ea # For example alternate-exchange
  routingkey: test-topic    # Routing key to subscribe to

Note

The arguments option can be omitted entirely for both queue and exchange if it is not necessary to set additional arguments. There is no fixed set of arguments which can be added and the entered argument names are not checked by the interface; they are passed on the server as-is. Check the RabbitMQ documentation to learn more about which exact arguments can be configured.

RabbitMQ Producer for publishing messages rabbitmq.Producer

To work with rabbitmq.Producer in MATLAB, first create an instance with rabbitmq.ConnectorProperties or configuration YAML-file as input:

% Create a Producer based on a configuration file
producer = rabbitmq.Producer(fullfile(rabbitMQProjectRoot,'config','example.yaml'));
% Or alternatively using ConnectorProperties
configuration = rabbitmq.ConnectorProperties();
producer = rabbitmq.Producer(configuration);

Then to send a message use publish with a routingkey and the actual message as input:

producer.publish('my-routing-key','Hello World');

RabbitMQ Consumer for receiving messages rabbitmq.Consumer

rabbitmq.Consumer offers two approaches for receiving messages from RabbitMQ in MATLAB. An event-based approach and a polling approach. These two different approaches correspond to the push- and pull approaches respectively, as described in the RabbitMQ Java API. As noted in this RabbitMQ Java API documentation the push (i.e. in MATLAB event based approach) is recommended. However, in MATLAB this will require the JAR-file to be loaded on the static Java class path rather than on the dynamic Java class path.

Event Based Approach

function consumer = EventBasedConsumerExample
    % Create the Consumer  with configuration file as input. Working with
    % rabbitmq.ConnectorProperties is supported here as well. Further set
    % eventBased = true to indicate to work with the event based approach 
    consumer = rabbitmq.Consumer( ...
        fullfile(rabbitMQProjectRoot,'config','example.yaml'), ...
        true);

    % Add a listener to the MessageReceived event
    addlistener(consumer,'MessageReceived',@onMessageReceived)


function onMessageReceived(~,message)
    % In the listener, as an example simply print the message
    fprintf('Message received: %s\n',message.message);

Polling Approach

function PollBasedConsumerExample
    % Create the Consumer  with configuration file as input working with
    % rabbitmq.ConnectorProperties is supported here as well. Further set
    % eventBased = false to indicate to work with the polling approach
    consumer = rabbitmq.Consumer( ...
        fullfile(rabbitMQProjectRoot,'config','example.yaml'), ...
        false);
    % Now actually start polling
    
    % In this example receive up to 3 messages then stop
    numReceived = 0;
    fprintf('Polling for messages...');
    % As long as we have not received three messages yet
    while numReceived < 3
        % Poll for a message
        message = consumer.pollMessage();
        if ~isempty(message) % If a message was received 
            % Display it
            fprintf('\nMessage Received: %s\n',message);
            % Increase the counter
            numReceived = numReceived + 1;
            fprintf('Polling for messages...');
        end
        fprintf('.')
        % Pause for a second before polling again
        pause(1);
    end
    % After 3 messages have been received
    fprintf('stopped.\n');

Deployment

When using this MATLAB Package in a MATLAB function deployed to MATLAB Production Server in order to send back replies/results to a RabbitMQ client (or in any other MATLAB Compiler (SDK) deployed component) it is important the correct functionality gets compiled into the deployed component. The MATLAB Compiler (SDK) dependency analysis should be able to automatically detect and include the MATLAB dependencies by itself but the JAR-file must be added manually to the component by adding it to the “Additional files required for your component to run” in the Compiler App or by using the -a option when working with mcc on the command line.

Any JAR-file compiled into a deployed component will be automatically added to the Java class path at runtime and any functions compiled into the component will be automatically on the MATLABPATH at runtime; so there is no need then to explicitly call startup in the deployed component. If possible the JAR-file is added to the static class path but there may be circumstances in which this is not possible and then it is loaded on the dynamic class path; this may make the event based consumer approach unavailable.