Mar 28th, 2011, 01:37 PM
SSL connections to RabbitMQ
I'm trying to work out how I'd make an SSL connection to a RabbitMQ server. I see that the com.rabbitmq.client.ConnectionFactory has several useSslProtocol() methods that seem like what I'm looking for. I've searched through the latest source of spring-amqp (as of Mon Mar 28 18:16:59 2011 +0100), and I don't see anything dealing with SSL anywhere. One way I think I could make it work is to create my own Rabbit ConnectionFactory, call one of the useSslProtocol() methods, and then inject the factory via constructor into the CachingConnectionFactory. Is that the recommended way to do it?
Mar 31st, 2011, 11:26 AM
Yes. There are a lot of features on the Rabbit ConnectionFactory and we don't really need to track them all in the Spring AMQP wrapper.
Originally Posted by zzantozz
Mar 31st, 2011, 01:55 PM
Okay, next question: has anybody been able to make an SSL connection to a Rabbit server with Java? I'm having no end of trouble with it. It's an older version--1.7.2--but I'm using the 1.7.2 client from the RabbitMQ page, and it just isn't being friendly. (This is just a basic test using the driver directly, not spring-amqp.) It keeps saying "SSL peer shut down incorrectly". I have managed to connect and get a message a few times, but lately I always get that error. Other clients (ruby and python) are connecting fine.
Apr 1st, 2011, 02:46 AM
I haven't tried with 1.7 and we don't support that with Spring AMQP anyway. The Hyperic plugin uses SSL and I think they support older versions, but I don't know if it goes that far back. You had better ask on the Rabbit mailing list if you want to use the Java client from 1.7 (but don't try it with Spring AMQP unless your use case is very basic, e.g. I know listener container stop/start lifecycle will not work before 2.3.1).
Apr 4th, 2011, 01:05 PM
It turns out that the SSL thing was somehow related to running Ubuntu + Java. A Ruby script on the same machine could connect fine, and the same Java program could connect from a Windows machine. I haven't tracked down what's going on there, but I'm moving on to other things right now.
One of those other things is trying out spring-amqp with version 1.8.1 of the rabbit client. For some reason, while RabbitMQ server version 2.x supports 0-8, 0-9, and 0-9-1 of AMQP, the 2.x java clients only support 0-9-1. I need 0-8 support. The API of the 1.8.1 client is very similar to the 2.x clients, and with a recent version of spring-amqp, only three changes were needed to make it compile against 1.8.1. I've successfully used it thus compiled to consume messages from a 1.7.2 server. It doesn't properly handle exceptions in the message listener, but I'm going to look at that. What is it about the "listener container stop/start lifecycle" that you were referring to that won't work without the 2.3.1 client?
Finally, while reading over the source of the SingleConnectionFactory, I noticed a problem with its connection management. The intent seems to be that this factory obtain a connection once, holds and reuses it for all subsequent calls, and then closes it on shutdown. This is supported by two properties that hold a Connection: connection and targetConnection. "connection" is the one that gets returned for use by other code and is wrapped with an adapter that ignores close() calls, and targetConnection holds the non-wrapped connection so that the connection factory itself can close it on shutdown. The targetConnection is created first, and then "connection" is targetConnection wrapped with an adapter. That's all well and good, but the adapter that the former connection is wrapped with is a SingleConnectionFactory.SharedConnectionProxy. The targetConnection is passed in as a constructor arg and is stored in the instance field SharedConnectionProxy.target. Then in SharedConnectionProxy.createChannel, it has the ability to detect that "target" is closed and to create a new connection. The problem here is that it only updates SharedConnectionProxy.target and not SingleConnectionFactory.targetConnection, so when the factory is shut down, it will try to close a connection that is already known to be bad, and the good connection won't be closed. Given that SharedConnectionProxy is an inner class of SingleConnectionFactory, the correct behavior could be gotten just by eliminating the target field from the former and directly accessing targetConnection in the latter.
Apr 6th, 2011, 02:42 AM
Problems with Ubuntu + Java usually means you have an unresolvable local host name. For some reason Ubuntu ships with /etc/hosts containing 127.0.1.1 mapped to the local hostname, and this is what Java thinks your IP address is by default. If you change the hostname to localhost it might work, or if you remove that line from /etc/hosts and map the host name (as discovered by java.net.InetAddress) to 127.0.0.1 (that's what I do).
Thanks for the insight on the ConnectionFactory. I think I noticed the same thing, or something related (https://jira.springsource.org/browse/AMQP-150).