CL-RABBIT - an interface from LispWorks to RabbitMQ =================================================== Version 0.1 I am very pleased to announce the release of version 0.1 of CL-RABBIT: an interface from LispWorks to RabbitMQ, an implementation of the AMQP messaging protocol. http://www.rabbitmq.com/ http://www.amqp.org/ It's released under an MIT-style license, a copy of which appears in each source file. Many thanks to Wiinz Limited for giving me permission to do all this and I'm sorry it's taken so long to get around to kicking the brute through the door. You'll note a lack of documentation. I assume knowledge of RabbitMQ; see comments in pkg.lisp and the example below. Then get in touch. Nick Levine ndl@ravenbrook.com 2009-04-02 Steps for running this: 1. See the parts list at the end of this post and get everything into place 2. Start the RabbitMQ server 3. Configure the system: *jni-lib-path* in jfli/jni.lisp and *libjvm* in cl-rabbit/rabbitmq.lisp 4. Use the build-java-classes.lisp tool to build cl-rabbit/java-classes.lisp from java-classes.lisp.src: CL-USER 1 > (load "c:/p4/user/ndl/lisp/jfli/build-java-classes.lisp") ; Loading text file c:\p4\user\ndl\lisp\jfli\build-java-classes.lisp ; Loading text file c:\p4\user\ndl\lisp\jfli\defsys.lisp ; Loading fasl file c:\p4\user\ndl\lisp\jfli\jni.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\jfli\jfli.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\jfli\process.ofasl #P"c:/p4/user/ndl/lisp/jfli/build-java-classes.lisp" CL-USER 2 > (build-java-classes "c:/p4/user/ndl/lisp/cl-rabbit/java-classes.lisp" (directory "c:/p4/user/ndl/lisp/cl-rabbit/*.jar")) ;; Reading c:\p4\user\ndl\lisp\cl-rabbit\java-classes.lisp.src ;; 22 def-java-class forms processed "c:/p4/user/ndl/lisp/cl-rabbit/java-classes.lisp" CL-USER 3 > (quit) ; Do not attempt to do anything else with this lisp! 5. Now we can play. - Load the code: CL-USER 1 > (load "/p4/user/ndl/lisp/jfli/defsys.lisp") ; Loading text file c:\p4\user\ndl\lisp\jfli\defsys.lisp ;; Creating system JFLI #P"c:/p4/user/ndl/lisp/jfli/defsys.lisp" CL-USER 2 > (compile-system "JFLI" :load t) ; Loading fasl file c:\p4\user\ndl\lisp\jfli\jni.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\jfli\jfli.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\jfli\process.ofasl ("JFLI") CL-USER 3 > (load "/p4/user/ndl/lisp/cl-rabbit/defsys.lisp") ; Loading text file c:\p4\user\ndl\lisp\cl-rabbit\defsys.lisp ;; Creating system RABBITMQ #P"c:/p4/user/ndl/lisp/cl-rabbit/defsys.lisp" CL-USER 4 > (compile-system "RABBITMQ" :load t) ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\java-classes.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\rabbitmq.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\pkg.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\errors.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\parameters.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\connection.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\channel.ofasl ; Loading fasl file c:\p4\user\ndl\lisp\cl-rabbit\message.ofasl ("RABBITMQ") CL-USER 5 > (in-package rabbitmq) # - Open a connection and a channel (I'll be lazy and use the same channel for outgoing and incoming messages), declare exchange and queue, bind everything together: RABBITMQ 6 > (setf my-connection (new-connection "localhost" "/")) # RABBITMQ 7 > (setf my-channel (new-channel my-connection)) # RABBITMQ 8 > (declare-exchange my-channel "my exchange" :direct) #<|com.rabbitmq.client.impl|::AMQIMPL$EXCHANGE$DECLAREOK. 2009159F> RABBITMQ 9 > (declare-queue my-channel "my queue") #<|com.rabbitmq.client.impl|::AMQIMPL$QUEUE$DECLAREOK. 21D050CF> RABBITMQ 10 > (bind-queue my-channel "my queue" "my exchange" "my routing key") #<|com.rabbitmq.client.impl|::AMQIMPL$QUEUE$BINDOK. 21CEEFD3> - Send a message into the void: RABBITMQ 11 > (setf outgoing-message (new-message)) # RABBITMQ 12 > (setf (message-id outgoing-message) "42" (message-body outgoing-message) "Hello, World") "Hello, World" RABBITMQ 13 > (publish outgoing-message my-channel "my exchange" "my routing key") NIL - And get it back again: RABBITMQ 14 > (consume-queue my-channel "my queue") "amq.ctag1_rabbit@gannet_20090402084407_" RABBITMQ 15 > (channel-arrived-count my-channel) 1 RABBITMQ 16 > (setf incoming-message (next-message my-channel)) # RABBITMQ 17 > (values (message-body incoming-message) (message-id incoming-message)) "Hello, World" "42" RABBITMQ 18 > Parts List ========== You will need the following: 1. CL-RABBIT 2. Rich Hickey's JFLI - this needed a bunch of fixes, so with Rich's agreement I released version 0.2 last summer and you'll find a link to that by visiting https://www.nicklevine.org/ 3. LispWorks (JFLI could be ported to other lisps but I don't think anyone's ever bothered) - I developed with LispWorks Pro 5.0 on Windows and we were planning to deploy on Linux so it was tested on that too; I checked it over today with LWW 5.1.2. 4. RabbitMQ: It's 18 months since I worked on this project. I tested it today against the materials to hand (RabbitMQ 1.2.0 which implements AMQP 0.8) while being very aware that RabbitMQ is now on version 1.5.3. I hope to have the time to "upgrade" soon but if you want to play with it sooner I'll be happy to advise. -- $Id: //info.ravenbrook.com/user/ndl/lisp/cl-rabbit/README.txt#4 $