Cross-device/cross-location Pub-Sub: Using Windows Azure Service Bus Topics Subscriptions in iOS with MonoTouch
Windows Azure has seen some updates over the past weekend. One small update is that the Service Bus and Access Control Service are no longer marketed inside the Windows Azure AppFabric brand but are now a substantial part of Windows Azure core.
The Windows Azure Service Bus has two basic feature sets:
- relayed messaging (through the Service Bus Relay service)
- brokered messaging (through queues, topics, subscriptions (and the deprecated message buffers)
In this post I show you how to use part of Service Bus’ REST API to create a cross-platform & cross-location publish & subscribe app by leveraging topics and subscriptions.
First of all, let’s launch the wonderful Service Bus Explorer tool and look at my Service Bus namespace:
As we can see there are no topics and subscriptions (and also no queues).
What we are going to do is have a .NET console app running on Windows to create a topic and a subscription on the Service bus with the REST API and send messages to the topic. Here is the essential piece of code to do this:
1: var broker = new BrokeredMessaging (serviceNamespace);
2:
3: try
4: {
5: token = broker.GetToken (issuerName, issuerSecret);
6:
7: string topicName = "newstopic";
8: string subscriptionName = "iphonesubscription";
9:
10: broker.CreateTopic(topicName);
11: broker.CreateSubscription(topicName, subscriptionName);
12:
13: while (true)
14: {
15: broker.SendMessage (topicName, "Hello " + Guid.NewGuid ().ToString ());
16: Thread.Sleep (5000);
17: }
18: }
19: catch (WebException we)
20: ...
Admitted, the actual heavy work is inside the BrokeredMessaging class. This class is just a simple wrapper around the REST API, and you can see some basic operations using WebClient to talk to the Service Bus in the AppFabric SDK samples (e.g. the Management Operations using REST sample).
The BrokeredMessaging helper class can be found in the sample projects download at the end of this post.
After we retrieved a token from ACS we create a topics and a subscription and send out messages in a loop:
These messages are sent to the Service Bus to a durable topic (which uses queues underneath). As long as there is no subscriber which gets and deletes the messages from the subscription we can see the messages sent to the topic in the Service Bus Explorer – here we have sent out 4 messages from the Console application:
Cool.
Now let’s use a subscriber to get the messages from the subscription. My goal was to have a native iOS app but built with C# entirely. Therefore I fired up MonoTouch and created a very simple iPhone app. For the super-sophisticated UI I used MonoTouch.Dialog, a highly recommend UI library to quickly create any forms-over-data user interface for iOS apps.
In order to talk to the Service Bus the MonoTouch project was using the exact same BrokeredMessaging class as my Windows console application. The joy of MonoTouch.
Again, the essential code (after getting a token from ACS) to get and delete messages from the SB subscription looks like this (the messages object is the list of elements in the UI to display the messages).
private void RegisterMessagesHandler ()
{
Task.Factory.StartNew (() =>
{
while (true)
{
try
{
var message = broker.ReceiveAndDeleteMessage (topicName +
"/Subscriptions/" + subscriptionName);
if (!String.IsNullOrWhiteSpace (message))
{
InvokeOnMainThread (delegate
{
messages.Elements.Add (new StringElement (message));
dvc.TableView.ReloadData ();
});
}
}
catch (Exception ex)
{
Console.WriteLine (ex);
}
}
});
}
Note: it may not be wise to store the Service Bus owner and shared secret directly in the device’s app – you know… or at least store it in the Keychain (sample with MT: http://www.wildsau.net/post/2011/02/01/iOS-Store-passwords-in-the-keychain-using-MonoTouch.aspx).
To convince you that there is no magic or cheating going on, this is the code from BrokeredMessaging to get the message from the subscription (and also delete it):
1: public string ReceiveAndDeleteMessage (string relativeAddress)
2: {
3: string fullAddress = baseAddress + relativeAddress +
4: "/messages/head" + "?timeout=60";
5:
6: Console.WriteLine ("\nRetrieving message from {0}", fullAddress);
7:
8: var webClient = new WebClient ();
9: webClient.Headers [HttpRequestHeader.Authorization] = token;
10:
11: var response = webClient.UploadData (fullAddress,
12: "DELETE", new byte[0]);
13: var responseStr = Encoding.UTF8.GetString (response);
14:
15: Console.WriteLine (responseStr);
16:
17: return responseStr;
18: }
Note: Console.WriteLine(…) is the mechanism in MonoTouch to write to debug output. Well…
Whenever we get a real and non-empty message we add it to the list view of our simple iOS app. Voila:
And to prove that everything worked as expected, the subscription is now empty and no more messages are in there:
Bingo!
Windows Azure Service Bus (together with the Windows Azure Access Control Service) enables us to send messages in an async manner to durable storage in the Cloud and subscribing to those messages (via topics and subscriptions) with literally any device, any platform, from any location!
The sample projects for VS 2010 and MonoTouch can be downloaded:
- SBTopicsPublisherREST (VS 2010)
- iServiceBusSubscriber (MonoTouch)
Hope this helps.
