technology from back to front

Archive for February, 2008

Unit testing in Java vs. Smalltalk

When you write unit tests, the minimal requirement before being able to try them out is that they compile. In Smalltalk, this means things like syntactic well-formedness, and perhaps the presence of global variables (i.e. classes) that you reference in the test method body.

It’s very quick and comfortable in Smalltalk to develop supported by unit testing: to write tests you know will fail, and refine away the failures until your test suite passes.

In Java, it’s much less comfortable, because besides the basic requirement of syntactic well-formedness, all the methods, classes, interfaces, and packages that your code relies on, directly or indirectly, must be present in the system before you can even try a run of the test suite! This makes for a less incremental style of development.

It would be very interesting to see a unit-testing framework for Java that simply treated a non-compiling test as a normal test failure, rather than a complete show-stopper, and which let you continue with the other tests in the suite. At the end of a run, it would include the non-compiling tests in the final reports just the same way as any other unexpectedly-failing test is reported.


Using AMQP to do cron-like scheduling

Barry Pederson‘s excellent py-amqplib Python AMQP client comes with a very cute little demo, demonstrating how easy it is to do sophisticated cron-like things with AMQP and RabbitMQ.

As Barry writes in the example, the trick is to “[fire] off simple messages at one-minute intervals to a topic exchange named ‘clock’, with the topic of the message being the local time as ‘‘, for example: ’2007.′, where the dow (day of week) is 0 for Sunday, 1 for Monday, and so on (similar to Unix crontab). A consumer could then bind a queue to the routing key ‘#.0′ for example to get a message at the beginning of each hour.”



How to run RabbitMQ’s experimental STOMP adapter

The code for the experimental STOMP adapter for RabbitMQ is distributed separately from the main server, at the moment. This post walks through the steps needed to try the adapter out, running it against a recent snapshot release of RabbitMQ. The perl Net::Stomp STOMP client is used to demonstrate the adapter in action, subscribing to a queue and sending a couple of messages to it.

You will need:

* Erlang R11B-5 installed, with erl and erlc on your path
* GNU Make
* A recent snapshot of RabbitMQ. For this example, I used [old link: ].
* A recent snapshot of the RabbitMQ STOMP adapter. An up-to-the-minute snapshot is available here (generated on-the-fly from a mercurial repository).

and, optionally, Perl to run the Net::Stomp example (or you could write your own examples using any other STOMP client, of course!); my Mac laptop comes with perl 5.8.8.

The first step is to unpack and compile the RabbitMQ server.

$ tar -zxvf rabbitmq-200801150657.tar.gz
$ cd rabbitmq-200801150657/erlang/rabbit/
$ make
$ cd ../../..

Once that’s done, fetch and extract the latest RabbitMQ STOMP adapter.

$ curl \
    | tar -jxvf -

Each time a commit is made to the STOMP adapter’s mercurial repository, the hexadecimal revision identifier changes, so the directory created by the unpacking of the snapshot you retrieve will be different. At the time of writing, the STOMP adapter’s directory was rabbitmq-stomp-7b00398dd81f.

To compile the STOMP adapter, you need to point make at the location of the RabbitMQ server codebase you’ve just compiled:

$ cd rabbitmq-stomp-7b00398dd81f/
$ make RABBIT_SOURCE_ROOT=../rabbitmq-200801150657

If you’ve managed to get through all those steps successfully, it’s time to try running the server. Issue the following “make run” command from the rabbitmq-stomp-7b00398dd81f directory:

$ make RABBIT_SOURCE_ROOT=../rabbitmq-200801150657 run
make -C ../rabbitmq-200801150657/erlang/rabbit run \
                RABBIT_ARGS='-pa '"$(pwd)/ebin"' -rabbit \
                        stomp_listeners [{\"\",61613}] \
                        extra_startup_steps [{\"STOMP-listeners\",rabbit_stomp,kickstart,[]}]'
NODE_IP_ADDRESS= NODE_PORT= NODE_ONLY=true LOG_BASE=/tmp  RABBIT_ARGS="-pa /Users/tonyg/dev/AMQ/scratch/rabbitmq-stomp-7b00398dd81f/ebin -rabbit                stomp_listeners [{\"\",61613}]           extra_startup_steps [{\"STOMP-listeners\",rabbit_stomp,kickstart,[]}] -s rabbit" MNESIA_DIR=/tmp/rabbitmq-rabbit-mnesia ./scripts/rabbitmq-server
Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:30] [kernel-poll:true]

Eshell V5.5.5  (abort with ^G)
(rabbit@walk)1> RabbitMQ 200801150657 (AMQP 8-0)
Copyright (C) 2007 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.
Licensed under the MPL.  See

Logging to "/tmp/rabbit.log"
SASL logging to "/tmp/rabbit-sasl.log"

starting database             ...done
starting core processes       ...done
starting recovery             ...done
starting persister            ...done
starting builtin applications ...done
starting TCP listeners        ...done
starting STOMP-listeners      ...done

broker running

Now, let’s try it out. I’ll use the Perl Net::Stomp module, available on CPAN.

$ sudo cpan -i Net::Stomp

The examples I’m going to try out are those from the Net::Stomp documentation – run perldoc Net::Stomp to read the originals. Save the following code into rabbit\_stomp\

# send a message to the queue 'foo'
use Net::Stomp;
my $stomp = Net::Stomp->new({hostname=>'localhost', port=>'61613'});
$stomp->connect({login=>'guest', passcode=>'guest'});
$stomp->send({destination=>'foo', body=>($ARGV[0] or 'test message')});

and the following code into rabbitmq\_stomp\

# subscribe to messages from the queue 'foo'
use Net::Stomp;
my $stomp = Net::Stomp->new({hostname=>'localhost', port=>'61613'});
$stomp->connect({login=>'guest', passcode=>'guest'});
$stomp->subscribe({'destination'=>'foo', 'ack'=>'client'});
while (1) {
    my $frame = $stomp->receive_frame;
    print $frame->body . "\n";
    last if $frame->body eq 'QUIT';

Run the receiver before the sender to make sure the queue exists at the moment the send takes place. In one terminal window, start the receiver:

$ perl ./

In another terminal window, run the sender:

$ perl ./
$ perl ./ "hello world"
$ perl ./ QUIT

The receiver’s window should contain the received messages:

$ perl ./ 
test message



You are currently browsing the LShift Ltd. blog archives for February, 2008.



2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us