Getting Started with Service Bus v2 (October CTP) - Connection Points

Last week at PDC we released a Community Technology Preview (CTP) of a new version of Windows Azure AppFabric Service Bus. You can download the SDK, Samples and Help on the Microsoft Download Center. There’s plenty new in this release and the first is the notion of Explicit Connection Point Management. In v1 whenever you started up a service and relayed it through the cloud over service bus we just quietly cooperated – this seems like a great idea until you think about a couple of advanced scenarios: Firstly: what happens when your service is offline but a sender (client) tries to connect to it? Well, we don’t know if the service is offline or the address is wrong (and there’s no way to differentiate); there’s no way to determine what’s a valid service connection point and what isn’t. There’s also no way to specify metadata about the service that connects (this is a HTTP endpoint, this endpoint is only Oneway). Also, you might have noticed that we added support for Anycast in v2 – how can you determine which connection points are Unicast (one listener/server and many senders/clients) and which are unicast (many load-balanced listeners and many clients)? That’s what connection points are for.

A Connection Point defines the metadata for a Service Bus connection. This includes the Shape (Duplex, RequestReply, Http or Oneway) and Maximum Number of Listeners and the Runtime Uri which acts as the service endpoint. Connection Points are managed as an Atom Feed using standard REST techniques. You’ll find the feed at the Connection Point Management Uri (-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints">https://<YourServiceNamespace>-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints)1 and it’ll look at little bit like this:

 <feed xmlns="https://www.w3.org/2005/Atom">
  <title type="text">ConnectionPoints</title>
  <subtitle type="text">This is the list of ConnectionPoints currently available</subtitle>
  <id>https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints</id>
  <updated>2010-11-01T20:53:53Z</updated>
  <generator>Microsoft Windows Azure AppFabric - Service Bus</generator>
  <link rel="self" 
        href="https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints" />
  <entry>
    <id>https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints(TestConnectionPoint)</id>
    <title type="text">TestConnectionPoint</title>
    <published>2010-11-01T20:51:11Z</published>
    <updated>2010-11-01T20:51:11Z</updated>
    <link rel="self" 
          href="https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints(TestConnectionPoint)" />
    <link rel="alternate"
          href ="sb://willpe-blog.servicebus.appfabriclabs.com/services/testconnectionpoint" />
    <content type="application/xml">
       < ConnectionPoint xmlns="" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"  ><br>        <MaxListeners>2</MaxListeners ><br>        <ChannelShape>RequestReply</ChannelShape ><br>      </ConnectionPoint > 
    </content>
  </entry>
</feed>

Writing some code to get your list of connection points is easy – in the rest of this post, I’ll show you how to (very simply) List, Create and Delete connection points. Before getting started, make sure that you’ve installed the October 2010 Windows Azure AppFabric SDK then create a new .Net Framework 4.0 (Full) Console Application in Visual Studio 2010.

  1. Add a reference to the Microsoft.ServiceBus.Channels assembly (its in the GAC, or at C:\Program Files\Windows Azure AppFabric SDK\V2.0\Assemblies\Microsoft.ServiceBus.Channels.dll if you need to find it on disk)

  2. Add 3 string constant containing your Service Namespace, Default Issuer Name and Default Issuer Key. You can get this information over at the Windows Azure AppFabric Portal:

        private const string serviceNamespace = "<YourServiceNamespace>";

    private const string username = "owner";

    private const string password = "base64base64base64base64base64base64base64==";

  3. Now define the hostname of your service bus management service (you can find this in the portal, too):

        private static readonly string ManagementHostName = serviceNamespace + "-mgmt.servicebus.appfabriclabs.com";

Access to Service Bus Management is controlled by the Access Control Service. You’ll need to present the ‘net.windows.servicebus.action’ claim with a value ‘Manage’ in order to have permission to Create, Read and Delete connection points. The default issuer (owner) is configured to have this permission by default when you provision a new account.

We’ll need to go ahead and get a Simple Web Token from the Access Control Service for our request. Note that, by default, the realm (relying party address) used for service bus management has the http scheme: you must retrieve a token for the management service using a Uri with the default port and http scheme even though you will in fact connect to the service over https:

  1. Get an auth token from ACS2 for the management service’s realm (remember, this must specify an http scheme):

         string authToken = GetAuthToken(new Uri("https://" + ManagementHostName + "/"));
    
  2. Add the token to the Authorization Header of a new WebClient and download the feed: – note that here we specify https

        using (WebClient client = new WebClient())

    {

    client.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + authToken + "\"");

    var feedUri = "https://" + ManagementHostName + "/Resources/ConnectionPoints";

    var connectionPoints = client.DownloadString(feedUri);

    Console.WriteLine(connectionPoints);

    }

Compile and run the app to see your current connection points (probably none). Now lets go ahead and create a Connection Point – to do this we just Post an Atom entry to the ConnectionPoint Management service. You can achieve this using classes from the System.ServiceModel.Syndication namespace3 but for clarity and simplicity we’ll stick to just using a big old block of xml encoded as a string – its not pretty this way, but it gets the job done!

  1. Define the properties of the new Connection Point – you need to specify a name (alphanumeric), the maximum number of listeners, a channel shape (Duplex, Http, Oneway or RequestReply) and the endpoint address (sometimes called a Runtime Uri) for the service:

        string connectionPointName = "TestConnectionPoint";

        int maxListeners = 2;

    string channelShape = "RequestReply";

        Uri endpointAddress = ServiceBusEnvironment.CreateServiceUri(

                                "sb", serviceNamespace, "/services/TestConnectionPoint");

  2. Now, go ahead and define the new Atom Entry for the connection point. Note how the name is set as the entry’s title and the endpoint address is set as an alternate link for the entry.

         var entry = @"<entry xmlns=""https://www.w3.org/2005/Atom"">
                        <id>uuid:04d8d317-511c-4946-bc1d-6f49b6f66385;id=3</id>
                        <title type=""text"">" + connectionPointName + @"</title>
                        <link rel=""alternate"" href=""" + endpointAddress + @""" />
                        <updated>2010-11-01T20:44:08Z</updated>
                        <content type=""application/xml"">
                          <ConnectionPoint xmlns:i=""https://www.w3.org/2001/XMLSchema-instance"" xmlns="""">
                            <MaxListeners>" + maxListeners + @"</MaxListeners>
                            <ChannelShape>" + channelShape + @"</ChannelShape>
                          </ConnectionPoint>
                        </content>
                      </entry>";
    
  3. Create a HttpWebRequest, add the ACS Auth Token, set the Http Method to Post and configure the content type as ‘application/atom+xml’:

         var request = HttpWebRequest.Create("https://" + ManagementHostName + "/Resources/ConnectionPoints") as HttpWebRequest;
        request.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + authToken + "\"");
        request.ContentType = "application/atom+xml";
        request.Method = "POST";
    
  4. Finally, write the new atom entry to the request stream and retrieve the response. You’ll discover an atom entry describing your newly created connection point in that response:

         using (var writer = new StreamWriter(request.GetRequestStream()))
        {
            writer.Write(entry);
        }
    
        WebResponse response = request.GetResponse();
        Stream responseStream = response.GetResponseStream();
        var connectionPoint = new StreamReader(responseStream).ReadToEnd();
        Console.WriteLine(connectionPoint);
    

If you re-run your application now, you’ll see that you’ve created a connection point which is listed in the feed we retrieved earlier. The last thing to do now is clean up after ourselves by issuing a delete against the resource we just created:

  1. Connection Point management addresses are similar to OData addresses – we address the specific connection point to delete by appending the connection point management Uri with the name of the item to delete in parenthesis:

        var connectionPointManagementAddress
    = "https://" + ManagementHostName + "/Resources/ConnectionPoints(" + connectionPointName + ")";

  2. Add the ACS auth token to the header of a WebClient and issue a Delete against the entry:

         using (WebClient client = new WebClient())
        {
         client.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + authToken + "\"");
            client.UploadString(connectionPointManagementAddress, "DELETE", string.Empty);
        }
    

So, there we go: Listing, Creating and Deleting Connection Points. Download the full example from Skydrive:

___

1 You’ll need to have a WRAP token in the Http Authorization Header to access this resource, so you can’t just navigate to it in a browser.

2 Read more about the Access Control Service at Justin Smith’s blog. Sample code to retrieve a token is included in the download at the end of this post.

3 An example of using the Syndication primitives to manipulate connection points is available in the October 2010 Windows Azure AppFabric Sample ‘ManagementOperations’