NMS is the .NET client library for using ActiveMQ, as well as other messaging systems. Unfortunately, it is the only complete one that I found, so using it isn’t really a choice (although I recommend coding your own STOMP client). I encountered many problems using it, but after working through them, everything seems to work.
Problem #1 - Downloading
Almost all the links to NMS point to Sprint.NET’s NMS build. If you notice the date in the link, the last time it looks to have been built is March 20, 2007. Also, almost all the links are broken on this site, which is never a good sign.
Instead, just download from Apache NMS . Since they don’t have releases, just checkout from SVN (https://svn.apache.org/repos/asf/activemq/activemq-dotnet/). Note that the link on their website points to (https://svn.apache.org/repos/asf/activemq/trunk/) which isn’t NMS.
Problem #2 - Application Hang
One issue that exists with the NMS library is a race condition when sending synchronous messages. Basically, when sending a synchronous message, if the transport connection dies after sending, the application waits forever. The Apache NMS documentation doesn’t mention it, but there is a query parameter that can be added to the connection URI that will timeout synchronous calls. So the URI would look like tcp://myactivemqserver.com:61616/?transport.requesttimeout=10000.
Even though this fixed the problem, it annoys me because it is very easy to fix without having to use a timeout parameter. I am thinking about trying to get a patch applied to the library but until then, just email me if you want to know the fix.
Problem #3 - Transport layer death
Even though request timeout fixes multitudes of problems, I want to make sure that the connection is destroyed in the event of any error. It isn’t documented very well, but this ExceptionListener event will bubble up anytime an error occurs in the transport thread and the socket gets closed.
//Create connection
IConnectionFactory factory = new ConnectionFactory(uri);
this.connection = factory.CreateConnection();
this.connection.ExceptionListener +=delegate(Exception e)
{
this.connection.Dispose();
this.connection = null;
}
There are two problems with doing this though. One, it isn’t very thread safe because the delegate WILL get called from a different thread. NMS is a multi-threaded library and there is no way around this. Thread safety should be handled better, but this is a trivial example to show the concept of the ExceptionListener event. Two, this event will get called if ActiveMQ returns an Exception message, which sometimes aren’t fatal. Normally, I have only seen these when disconnecting so just detach the event handler from the event before closing the connection.