Playing with MSMQ transport in WSE2

Tags: SOA

As i I've been working in the new messaging framework we are developing i started to look for existing implementations for custom transports for WSE2.

So far i have found the following: MSMQ, SMTP, UDP and SQL. The one using MSMQ is from the excellent writer and MVP Roman Kiss (published at CodeProject) and i enjoyed this article very much. Roman also have written other fine articles, so give then a look.

Well, let's get to the point. I've been using this code as a base to build some MSMQ transport for WSE2 and I stumbled with a very annoying bug.
In the code that registers a new SoapReceiver the article sample code always pass a new instance of a receiver object instead of passing the Type of the receiver you want to use.
The SoapReceivers.Add method allows registering a new receiver using two different overloads: using an object instance or an object type.
The two behaviors go in the opposite direction as one uses always the same receiver instance for all process and the other way implies a creation of a new receiver at runtime when it’s needed.
So, I realize that the code in the SoapMsmqInputChannel from the article only supports only the first way of doing things, that’s it passing an instance and not an object type.
This bug was annoying because the behavior of the failure was very strange. When I try to pass an object type to the SoapReceivers.Add method all went fine until I discover that the message wasn’t dispatched to my receiver object because it's never found in the receivers collection.
Fortunately the bug is very easy to fix. Just add the code to take into account that the thing you found in the SoapReceivers collection maybe it’s an instance of an SoapReceiver object or maybe it’s an object Type and it’s your responsibility to create the instance.

To make the story short, the method Enqueue can be rewritten as follows:

public override void Enqueue(SoapEnvelope message)
{   
 // get the receiver for this endpoint
        SoapReceiver receiver;
 object recv = SoapReceivers.Receiver(_endpoint);

 if( recv is Type )
        {
            receiver = (SoapReceiver)Activator.CreateInstance((Type)recv);
        }
        else
        {
     // try to cast
            receiver = recv as SoapReceiver;
         }

 if(receiver != null)
 {
  // synchronous process message workflow
                // through the pipeline to the endpoint handler
  receiver.ProcessMessage(message);
 }
 else
  throw new Exception(string.Format(
                    "Missing a receiver for endpoint={0}",
                     endpoint.Address.Value));
}

 

I hope that this post help someone with the same problem I come across. I will continue working with this code making some enhancements and adding some features we need, and I will be posting my experiences here.

Best regards,


PS: i haven't compiled the above code (i'm writing it right here and now) so excuse me if it has some error or imperfection.

Andrés G Vettori
MCSE/MCSD/MCT
Leader of the C# Community of the Microsoft Users Group Argentina

No Comments