MSMQ Logging and Entlib with Remote Private queues

Friday, March 04 2005

As I have stated before, the client I am at has recently decided to adopt EntLib into their development standards.  It was not an easy decision for them and it took quite a bit of discussion on the matter.  The first part that is being absorbed by the standards is the Logging and Exception Handling blocks.  The client has chosen to use the MSMQ distribution strategy for logging in order to centralize the logs of all their applications into one database.

Based on MSMQ best practices we recommended using private queues instead of public ones.  This cuts down the necessity for Active Directory to be involved.  The client had not previously been using MSMQ in any of their current systems.  This lead to an issue about communication with Remote Private queues.  Basically the issue is the MSMQ Distribution Strategy for EntLib out of the box will NOT work with remote private queues.  Here's why:  to hit a remote private queue with EntLib (which is using System.Messaging under the hood) we had to use the FormatName option of Direct.  The Direct communications does NOT allow for the querying of queue properties.  Also, you can NOT query the queue properties of a remote private queue by design.  The MsmqLogDistributionStrategy class used to send the messages uses the following bit of code in it's SendMsmqMessage method:

                    MessageQueueTransactionType transactionType = (messageQueue.Transactional)
                        ? MessageQueueTransactionType.Single
                        : MessageQueueTransactionType.None;

                    messageQueue.Formatter = new XmlMessageFormatter();
                    messageQueue.Send(serializedEntry, transactionType);
                    messageQueue.Close();

This creates an instance of the queue as a reference on the client.  It them checks the queue to see if the it is Transactional or not.  As stated before you CAN NOT check the properties of a private remote queue, or any queue you connect with using the FormatName option of Direct.  This code was causing an exception and the messages were not being sent to our remote private queue.

How to fix this?

Well, we discussed several options and the client choose to go with public queues, which nullifies the issue since you can connect to the public queue with just computername\queuename instead of having to use the FormatName option Direct.  It does mean that they have to have some reliability on their AD to be up and running at all times and that now the queue is discoverable in AD.  It will also decrease performance of the queue as the MSMQ client software will query the AD for information before sending the message.

Now, if you really want to use EntLib logging MSMQ distribution strategy with a remote private queue here is the other option we suggested.  Create a new class that duplicates the MsmqLogDistributionStrategy class and remove the check of the transactional type.  We toyed with inheriting from the MsmqLogDistributionStrategy class, but found that other issues came up with having to get at private members within the MsmqLogDistributionStrategy in the derived class, such as the configuration data, etc.  It's such a small class anyway that just copying the class, renaming it and then modifying it was a decent option for us.

Why the check for the queue being transactional is being done I'm not quite sure.  Hopefully this will help someone else.  Also, if you find that I've stated anything incorrectly here, or know of another way you plan on handling this, please leave a comment.

Comments

Friday, March 04 2005 6:30 AM Mike LorengoT said:

Hey,


I just wanted to drop you a note to let you know how much I appreciate your posting of these issues. I'm about 2 steps behind you, which from my perspective is a great place to be as your finding all the roadblocks and providing the detours. Thanks again!


Monday, March 07 2005 5:28 AM MikeWodTrueht said:

Glad you're getting some use of it.


Wednesday, March 30 2005 12:32 PM Gary Sandher said:

I like to access private queue remotely in my application using EntLib new Logging Application Block. I tried your solution of creating new class based on MsmqLogDistributionStrategy e.g MsmqLogDistributionStrategyMyStrategy (Removed the check for transactional property) and built the logging block. Ypu have not said anything about changing reference for MsmqLogDistributionStrategy in MsmqDistributionStrategyData e.g


public override string TypeName


{


get { return typeof(MsmqLogDistributionStrategy).AssemblyQualifiedName; }



The new strategy will not be loaded from the assembly unless chnage is made to this file.


I have couple questions


1. Why do you suggest to create new class instead of modifying MsmqLogDistributionStrategy class?


2. Did you created custom distributor strategy with new class e.g. MsmqLogDistributionStrategyMyStrategy. in which case you need MsmqLogDistributionStrategyDataMyStrategy.


3. What are the steps to create custom distributor strategy?


Friday, April 08 2005 11:54 AM mvwood said:

Gary,



Thanks for the feed back.



1. You can easily modify the MsmqLogDistributionStrategy class if you wish. That is a pretty easy option to take as well. For why I didn't recommend it was that I thought it was easier to generate a new class that dealt specifically with the remove private queues and not change how the one out of the box worked. That way the client could plug in the new custom one, or the original (if they went to a model of using both private and public queues for some reason). Again, I have no idea why the original design included this transactional check for something like logging, but who knows.



2. No, I did not create one, which I now feel ashamed about advocating it without putting one together. I knew in theory that just copying the code out would create a new strategy without the check. You are very much correct that you would then need your own strategy data class to load the configuration information out.



3. The answer to this would be a post all to itself and be somewhat involved. I don't want to give an "all you have to do is" comment here. A friend has created a Web Service Distribution Strategy and gave me the code, and since he is mostly a DBA developer (or has been in the past) it must not be too hard. :)


Wednesday, June 22 2005 4:43 PM Thejuan said:

The check for whether the queue is transactional is because if the queue is transactional and you call the send overload without specifying a transaction type. The message goes to the dead letter queue.



If you call send with a transaction type of single or automatic on a queue that is not transactional it throws an error.


Sunday, June 26 2005 3:07 PM mvwood said:

Thanks Thejuan for shining some light on why this check was made.


Monday, March 13 2006 3:47 PM Tony said:

Does anyone know how to make it work with Enterprise Library 2.0 using remote library queue? I have been unsuccessfully try to get this working.



Thanks


Wednesday, March 15 2006 9:59 AM mvwood said:

Tony,



Sorry I don't have time to look into this for you. You'd probably reach a much wider audience for this question over on the GotDotNet EntLib forums <http://www.gotdotnet.com/codegallery/messageboard/messageboards.aspx?id=295a464a-6072-4e25-94e2-91be63527327>. Most likely you'll at least get some insight from people who are on to using EntLib 2.0...(sadly I'm not one of those lucky types yet).


Friday, March 17 2006 11:57 AM Tony said:

I figured to get it working to access private queue. User "FormatName:DIRECT=OS:computer_name\PRIVATE$\queue_name.



Monday, March 20 2006 9:37 AM mvwood said:

Thanks for posting your finding back here!