Mike Taulty's Blog
Bits and Bytes from Microsoft UK
SQL Server 2005 Service Broker and WSE2.0 SOAP Messaging

Blogs

Mike Taulty's Blog

Elsewhere

Archives

Following up on this previous post about SQL Server 2005 Service Broker, I've been writing a SOAP message transport for the Web Services Enhancements (WSE) 2.0 to move messages using ServiceBroker whilst still gaining advantage of the security, policy, addressing features of WSE2.0.

It's important to say that this is purely for fun because it involves installing WSE2.0 on top of the beta .NET Framework 2.0 and there is no way in which the WSE team or the .NET framework team are going to support that kind of scenario.

The solution files and source code are all in this zip file here which you can download and play with.

I started with the December Community Tech Preview of SQL Server 2005 and the accompanying Visual Studio 2005 build - these are available from MSDN Subscriber Downloads for you to get hold of.

Following up on my previous post I've already created constructs in SQL for SoapMessage, SoapContract and also that post details creating some services and queues: SendingService, SendingQueue and ReceivingService, ReceivingQueue. The services and queues aren't set in stone here but the SoapMessage/SoapContract stuff is baked into my code.

The implementation is not perfect by any means and I'm sure that there are bugs in there but it seems to work reasonably well in terms of both synchronously and asynchronously sending/receiving on both one-way and two-way conversations.

In terms of the structure of it, there are a number of projects as below;

AsyncUtilities - a simple library with a couple of helper classes that try and make the wrapping up of existing asynchronous code (such as SqlCommand.BeginExecuteReader) easier to deal with.

BrokerUtilities - this provides a simple library that lets me send and receive messages through the ServiceBroker. It's just using dynamic SQL and ADO.NET 2.0

BrokerTransport - this implements the WSE2.0 transport itself, making use of the BrokerUtilities library to send messages backwards and forwards.

SQL Service Broker Scripts - this contains a single script to create my SoapMessage and SoapContract definitions and a couple of test services.

Test Applications - contains 3 test applications. The first 2 are simple console applications that send/receive messages through Service Broker. The third is a Windows application that needs to be run twice and then has a "conversation with itself" :-)

By way of some explanation (as there are no comments in the code)...

AsyncUtilities

This project contains a class named AsyncResultWrapper - I blogged about something very similar to this the other day - it's just a little class to help make the wrapping up of another class which does asynchronous operations a little easier.

The other class here is CompletedAsyncResult which is a trick implementation of IAsyncResult which always will return "Done"! immediately. There's a place where I need this later on.

BrokerUtilities

There's a class called SqlUtility here which makes open SqlConnections for me and transactional SqlCommand instances which are expecting CommandText rather than stored procedures etc. Note that the view here is that given a database server and a database name we can generate a connection string and connect to the database (i.e. we just assume that we can use integrated security) - if that wasn't the case then you'd need to tweak this class and possibly also the soap.broker Uri that I'll talk about later.

The other two classes are MessageReceiver and MessageSender which are static classes offering methods for sending XML through ServiceBroker. Essentially the methods look like;

void MessageSender.SendMessage( DatabaseServer, DatabaseName, DestinationService, SendingService, XmlMessage )

List<XmlReader> MessageReceiver.ReceiveMessage( DatabaseServer, DatabaseName, ReceivingQueue )

There are corresponding asynchronous versions of these methods as well. Internally they're very simple in that each uses dynamic SQL to send/receive messages and also there's an assumption in the sending of messages that each single message will be sent in its own unique dialog and that it's ok for the receiver to receive everything off its queue without checking conversations. What I'm really saying is that I don't do conversations here!

Note also that when ServiceBroker is sending for you it needs to know about the SendingService and the ReceivingService but when it's receiving it needs to know about the ReceivingQueue. That's how the programming model works.

BrokerTransport

This implements the WSE 2.0 transport on top of the BrokerUtilities library. Implementing a WSE 2.0 transport isn't too bad (at least at the level that I've done my implementation here which is less than bulletproof).

The first thing you've got to do is go ahead and implement ISoapTransport and you'll spot that in my BrokerTransport.cs file. This interface is really about returning implementations of ISoapInputChannel and ISoapOutputChannel based upon a transport address that you're given by the WSE. Note that I make a fairly simple assumption about the mapping between EndpointReference and input/output channels which is probably not quite right in all scenarios.

In terms of the input and output channels - they're in BrokerInputChannel.cs and BrokerOutputChannel.cs - these make use of the underlying BrokerUtilities code to send/receive messages synchronously or asynchronously.

The other interesting thing here is the BrokerUri class which is, again, a very simple thing. In terms of addressing a SOAP message to travel through ServiceBroker I've said that we'll use a Uri that looks like this;

soap.broker:<database server name>-<database name>-service:<service name>

soap.broker:<database server name>-<database name>-queue:<queue name>

This needs a bit of explanation. When you're sending a SOAP message you need to stick an address on it to say where it's going to. This address will look like soap.broker:myServer-myDatabase-service:DestinationService and that's enough to get us where we want to go. However, ServiceBroker also wants to know where did it come from? in order to begin a conversation. Consequently, when sending, you still have to supply a ReplyTo address on your SOAP message with something like soap.broker:myServer-myDatabase-service:OriginatingService.

So, that's possibly OK and that's what my code expects. However, when you're receiving messages with ServiceBroker you actually pull them from a queue rather than receiving them "for a service". Consequently, if you want to listen for SOAP messages with this transport you need to use a Uri like soap.broker:myServer-myDatabase-queue:MyQueue.

If you run the sample applications you'll see how they're set up.

TestApplications

The main test application here is just called TestApplication. It uses the "lower level" SoapSender and SoapReceiver model of programming in WSE.

The idea is that you run two of these applications and they "talk" to each other.

You set up each instance as a "sender" by specifing its service name and the service name it sends to. You also need to have it listen as well so you specify the queue that it reads from.

Once you've got two of them up and running you click "Ready to Listen" on both of them and then on one of them you click "Send First Message". That instance will then generate a shape, draw it and send it to the other instance. That second instance will then draw it, wait a little while before generating its "reply shape" and sending it back. They then just go back and forward sending shapes to each other.

If you use my SQL creation script to generate Services/Queues then you'll have the same names as me and that will let you use the "Send Defaults" and "Receive Defaults" buttons to pre-populate the form with the right values based on that script.

The second set of applications here are called Sender and Receiver and they're console apps which speak to each other. The names of the queues and services are baked into the code here so if you use this you'll need to have the same queues/services that I have.

The idea here is that you run both Sender and Receiver. Every time you hit return on the Sender it will send a message to the Receiver which will then send a reply. Both sides of the conversation just write their messages to the console when they receive them. Again, this is using the "low level" SoapSender/SoapReceiver API rather than the higher level SoapService/SoapClient.

SQL Service Broker Scripts

This is a single SQL script which sets up the required SoapContract, SoapMessage and, if you want to, also creates some services and queues which the demos make use of.

Configuration

If you want to make use of the transport it's important to remember that WSE 2.0 doesn't just know about it but has to be told via way of a configuration file change. The configuration file should look something like this (as a miniumum);

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <configSections>

    <section name="microsoft.web.services2" type="Microsoft.Web.Services2.Configuration.WebServicesConfiguration, Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

  </configSections>

  <microsoft.web.services2> 

      <messaging>

            <transports>           

                  <add scheme="soap.broker" type="BrokerTransport.BrokerTransport,                 BrokerTransport"/>           

            </transports>  

      </messaging>     

  </microsoft.web.services2>  

</configuration>

That's pretty much  it - I'm not planning to do any more with this transport unless someone comes back and has something interesting to do with it or would like to change it. If someone does take it and improves it or fixes it then feel free to drop a comment here saying that you've done so as it'd be interesting to see.


Posted Fri, Feb 25 2005 2:05 AM by mtaulty

Comments

mtaulty wrote re: SQL Server 2005 Service Broker and WSE2.0 SOAP Messaging
on Thu, Mar 17 2005 9:19 PM
You didn't have to build it on .NET 2.0 framework. The 1.1 framework which is supported by the WSE folk would work just fine.

Also didn't you consider using the sample ServiceBrokerLibrary for this?
mtaulty wrote re: SQL Server 2005 Service Broker and WSE2.0 SOAP Messaging
on Sun, Mar 20 2005 2:43 PM
Hi Rushi,

Yes, you're right - I built this on .NET Framework 2.0 mainly for my own reasons which are that I have SQL 2005 and VS 2005 both installed into a single VPC image so it was easier for me to work this way.

I didn't use the sample library for this - again it was mostly around me playing around with the ServiceBroker more than anything else.

Thanks,

Mike.
mtaulty wrote re: SQL Server 2005 Service Broker and WSE2.0 SOAP Messaging
on Sun, Jun 19 2005 8:33 PM
Hi Mike,

Do you know how one would send a soap message from a stored procedure in SQL Server 2005?

Thanks,

Shirley