Building the RabbitMQ Erlang AMQP Client

I thought I’d jot down my notes from getting the experimental rabbitmq erlang amqp client to work, since http://hopper.squarespace.com/blog/2008/1/12/introducing-the-erlang-amqp-client.html is a little out of date.

This assumes you already have erlang (I’m using R13B01), OTP, eunit, and mercurial installed.

In a common base directory (~/rabbitmq), clone all the necessary tools:

~/rabbitmq> hg clone http://hg.rabbitmq.com/rabbitmq-erlang-client
~/rabbitmq> hg clone http://hg.rabbitmq.com/rabbitmq-server
~/rabbitmq> hg clone http://hg.rabbitmq.com/rabbitmq-codegen

Then build the rabbitmq-erlang-client:

~/rabbitmq> cd rabbitmq-erlang-client
~/rabbitmq/rabbitmq-erlang-client> make

(Note: if you don’t see the file ebin/amqp_client.app, run: make ebin/amqp_client.app)

Now test the client out. This assumes you’ve already started rabbitmq with the default guest user:

~/rabbitmq/rabbitmq-erlang-client> erl -pa ebin -pa ../rabbitmq-server/ebin
1> amqp_connection:start_network().
<0.35.0>

Next, I want to be able to use the client from other projects, so I can either copy over the ebin and include files (look in rabbitmq-erlang-client/dist), or create symlinks into system erlang directories.

Now, assuming we have all our paths setup correctly so that we can compile against the amqp_client and rabbit_common apps, how do we start writing and reading messages? Coming from the ruby world, and being used to STOMP messaging, I was surprised by how many steps are involved in just doing basic gets and publishes (the ruby amqp gem is simple to use, btw).

After spending a bit of time studying rabbitmq-erlang-client/test/test_util.erl (A great resource!), I’ve distilled some simplified code to see the basics of this client library, and start writing and reading messages quickly. Most of this code was copied right out of the test_util.erl file, and many details are skipped (take a look at that file for more detailed code!):

-module(amqp_test).
-compile(export_all).

-include(“amqp_client.hrl”).

t() ->
    Connection = amqp_connection:start_network(),
    Channel = amqp_connection:open_channel(Connection),
    Q = <<“a.b.c”>>,
    X = <<“x”>>,

    setup_exchange(Channel, Q, X),

    Payload = <<“hello, world!”>>,
    ok = basic_publish(Channel, X, Payload),
    {ok, Payload} = basic_get(Channel, Q),
    {ok, []} = basic_get(Channel, Q),

    amqp_channel:close(Channel),
    amqp_connection:close(Connection)

% sets up the queue and topic exchange, and ties the exchange to the queue
setup_exchange(Channel, Q, X) ->
    amqp_channel:call(Channel, #‘exchange.declare’{exchange = X,
                                                   type = <<“topic”>>}),
    amqp_channel:call(Channel, #‘queue.declare’{queue = Q}),
    Route = #‘queue.bind’{queue = Q,
                          exchange = X},
    amqp_channel:call(Channel, Route),
    ok.

basic_publish(Channel, X, Payload) -> 
    Publish = #‘basic.publish’{exchange = X},
    ok = amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}),
    ok.
basic_get(Channel, Q) ->
    case amqp_channel:call(Channel, #‘basic.get’{queue = Q, no_ack = true}) of
        {#‘basic.get_ok’{}, #amqp_msg{payload = Payload}} -> {ok, Payload};
        #‘basic.get_empty’{} -> {ok, []};
        Other -> {error, Other}
    end.

Comments are closed.