Using a messaging protocol to facilitate communication between different applications is nothing new, in fact it has been the defacto standard for fast and reliable communication.  It is important to note, this is a type of communication that you would usually use when communicating between different hosts. When working on a single host, there are simpler and more scalable methods that you can use (e.g. sockets).

What is needed

Let us take an example of three applications running on two different servers. To simplify this example, one application will be master and the other two will serve as slaves. Master application will provide work tasks, which will slave execute and report back progress. It seems simple enough, let us make it happen.


Message Bus, enter ActiveMQ

ActiveMQ is one of the most popular solutions for open source messaging, there are some other popular alternatives such as RabbitMQ, Zer0MQ, etc. The following examples will be less so oriented on the underlying technology, and more so on functional examples that will use STOMP. STOMP is a protocol, and as long as the messaging server supports that protocol you should be able to change it.

Installing ActiveMQ is really simple, just follow getting started guide. After ActiveMQ has been installed we will need to make some adjustments to its configuration. Communication between master and slave will be implemented via two channels, one for broadcasting messages to slaves and one for replies from mentioned slaves.

In messaging there are two major types of communication channels topics and queues. Rules of thumb would be if you would like to broadcast messages you would use topics, if you wanna process messages in ordered fashion you would use queues. For our example it would be good to broadcast messages to slaves via topic and to process their results via the queue.

Since we are clear on what to do, let us create a topic, and queue on ActiveMQ. After successfully installing ActiveMQ you can find it’s configuration in /opt/activemq/conf/activemq.xml.

  	<!-- We create user that we will use to connect to ActiveMQ -->
        	<authenticationUser username="foo" password="bar" groups="foo,everyone"/>
    <!-- We create topic(s) and queue(s) under namespace "myapp" -->
        			<authorizationEntry topic="myapp.>" write="foo" read="foo" admin="foo" />
        			<authorizationEntry queue="myapp.>" write="foo" read="foo" admin="foo" />

Change configuration by adding above snippets and restart ActiveMQ, sudo service ActiveMQ restart. The important thing to note is when we define topic/queue as myapp.> this allows us to create multiple topics/queues under that namespace e.g. myapp.reply or

Connecting to message bus

For interaction, via STOMP we are going to use stomp gem, for a more straight forward and simple approach. As gem’s README points out this is really simple to do. I am going to assume that you are running ActiveMQ locally with default port localhost:61613 our example will reflect that.

client ="foo", "bar", "localhost", 61613)

Pretty simple so far now let us publish a message from our master node to topic

	original_message   = { :foo => 'test', :bar => { :test => [1, 2, 3, 4]}}
	marshalled_message = Marshal.dump(original_message)
	client.publish('', marshalled_message)

On the slave side we need to listen for these messages, or subscribe to them so we do that by initializing client and subscribing.

    client ="foo", "bar", "localhost", 61613)
    client.subscribe('') do |marshalled_message|
    	original_message = Marshal.load(marshalled_message)
    	# process message

That is all functional pieces that we need to create more complex applications. There is a convention that we in ABH use and that is replying to messages to queues with reply suffix. For this master and slaves relationship, or slaves would reply to queue /myapp/reply and master node would have the responsibility to handle these messages.


Keep in mind that demonstrated solution had blocking properties, and as such might not be the best solution for Rails stack. For Rails I would recommend EventMachine based STOMP client. If enough interest has been shown I can write an article on how to implement this solution in existing Rails applications.

Keeping track of sent messages

One important detail that should be included is request_id for messages that will be going between master and slaves. That is the simple way to keep track of jobs that were dispatched to slaves and their results. You can create UUID by using:

	require 'securerandom'
	request_id = SecureRandom.uuid

That way when you receive a response on queue /myapp/reply you can match it to sent request.


Hopefully, this will be enough to get you started. This article can be easily extended by previously mentioned reactor based EM STOMP client or by adding security to message since if SSL is not used these will be easy to read if intercepted. If enough interest is shown, will expend this topic more.

Decorator pattern
Software DevelopmentTech Bites
January 23, 2023

Decorator pattern

Design patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can customize to solve a particular design problem in your code. A decorator pattern allows users to add new functionality to an existing object without altering its structure. This design pattern comes under…
JPA annotations in Hibernate
Software DevelopmentTech Bites
January 5, 2023

JPA annotations in Hibernate

Suppose you have wondered how we interact with relational databases without (directly) using SQL queries. In that case, the answer usually lies in Object-Relational Mapping (ORM), which will do the job of converting Java objects and statements to database tables and related queries. Hibernate comes into this story as the…
Dynamic programming
Software DevelopmentTech Bites
December 9, 2022

Dynamic Programming

Dynamic programming is both a mathematical optimization method and a computer programming method. By definition, it is a technique in computer programming that helps to efficiently solve a class of problems with overlapping subproblems and optimal substructure properties. It refers to simplifying a complicated problem by breaking it into simpler…

Leave a Reply