Azure for Developers Tutorial Step 5: Adding messages to a queue

This is the fifth step of the Azure for Developers tutorial, in which we set up a WCF service running in Azure to provide CRUD operations to a client application. For more information, please check out the Introduction.

In this step, we will add a method to our service to allow the user to put messages on the queue. We will let him pass in the first and last name, and we’ll retrieve the Favorites and then put a message on the queue with the four fields in it.

Open CustomerServices.svc in our project. Add these using statements at the top:

using Microsoft.WindowsAzure.StorageClient;
using System.Diagnostics;
using Microsoft.WindowsAzure;
using System.Net;
using Microsoft.WindowsAzure.ServiceRuntime;

Then in the class itself, add these private variables.

private static bool storageInitialized = false;
private static object gate = new Object();
private static CloudQueueClient queueStorage;
private static CloudQueue queue;

We will add a method for adding a message to the queue. In that method, we will call InitializeQueue(). The first time the queue is initialized, it will set a boolean called storageInitialized to true, and then subsequent calls will know it is already initlaized. The object gate is used for locking, to make sure multiple people don’t initialize the queue at the same time.

CloudQueueClient is the client for accessing the queue, and CloudQueue is the queue itself.

So let’s add InitializeQueue(). I’ve added comments in-line to explain what it’s doing.

//initialize the queue, but only the first time 
private void InitializeStorage()
{
  //if it's already initialized, return
  if (storageInitialized)
  {
    return;
  }
  //lock the object
  lock (gate)
  {
    //if someone else initialize the queue while you had the object locked,
    //  return
    if (storageInitialized)
    {
      return;
    }
    //try initializing the queue
    try
    {
      Trace.TraceInformation("[CustomerServices.InitializeStorage] Initializing storage queue");
      // read account configuration settings and get a reference 
      //  to the storage account
      CloudStorageAccount storageAccount =
          CloudStorageAccount.Parse(
          RoleEnvironment.GetConfigurationSettingValue(
          "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"));

      // get a reference to the queue client
      queueStorage = storageAccount.CreateCloudQueueClient();
      // this uses the entry in GlobalStaticProperties that is set in the role config
      queue = queueStorage.GetQueueReference(GlobalStaticProperties.ProcessQueueName);
      //create the queue if it doesn't already exist
      queue.CreateIfNotExist();
    }
    catch (WebException ex)
    {
      //try to give some help
      Trace.TraceError("[CustomerServices.InitializeStorage] WebException thrown trying " 
        + " to initialize the storage services. " 
        + " Check the storage account config settings. If running locally, "
        + "be sure Dev Storage svc is running. Exception = {0}",
          ex.ToString());
      return;
    }
    catch (Exception ex)
    {
      Trace.TraceError("[CustomerServices.InitializeStorage] Exception thrown trying "
        + "to initialize the storage. Exception = {0}", ex.ToString());
      return;
    }
    //this is only set to true if it doesn't throw an exception
    storageInitialized = true;
  }
}

We’re going to add a method to add a message to the queue. This actually formats the message and adds it to the queue. (In my production services, I put this code in a separate class.) Our message is going to be a comma-delimited string. I always pass a ‘command as the first entry in case I want to use the queue to process different requests.

If any of the four input fields have commas in them, they won’t parse right. At GoldMail, we hit this in a case where we are passing the user agent string to the backend in a message, and the user agent string had commas in it. We had to put in special handling for this case.

If you have more information than you want to put in a string, you can write it to blob storage and put a URL to the file in blob storage in the message.

Here’s our new method; add this to ComposerServices.svc.cs.

public string SubmitToQueue(string firstName, string lastName)
{
  //call to make sure the queue exists
  InitializeStorage();
  string errorMessage = string.Empty;
  string favoriteMovie = string.Empty;
  string favoriteLanguage = string.Empty;
  //get the favorites info for the name passed in
  errorMessage = GetFavorites(out favoriteMovie, out favoriteLanguage,
      firstName, lastName);     
  if (errorMessage.Length == 0)
  {
    //I'm passing the message as a comma-delimited string. Format the string.
    string msgString = String.Format("process,{0},{1},{2},{3}", 
      firstName, lastName, favoriteMovie, favoriteLanguage);
    //set the message
    CloudQueueMessage message = new CloudQueueMessage(msgString);
    Trace.TraceInformation("[SubmitToQueue] Message passed to queue = {0}", msgString);
    //add the message to the queue
    queue.AddMessage(message);
  }
  else
  {
    errorMessage = "Entry not submitted to queue. "
      + "Error when retrieving favorites = '" + errorMessage + "'.";
    Trace.TraceError("[SubmitToQueue] firstName = {0}, lastName = {1}, {2}",
        firstName, lastName, errorMessage);
  }
  return errorMessage;
}

Now let’s add the corresponding operation contract  to the interface. If you don’t do this, the method won’t be exposed to the client. Open ICustomerServices.cs and add the operation contract.

[OperationContract]
string SubmitToQueue(string firstName, string lastName);

Run the service locally. Now let’s change the client to add the entries to the queue. Open the TestService. Right-click on the service reference to our service and select Update Service Reference and click OK. This should expose the SubmitToQueue method. Add this to the DAC.cs class in the test client:

  internal static string AddToQueue(string firstName, string lastName)
  {
    string errorMessage = string.Empty;
    CustomerSvc.CustomerServicesClient prx = getClient();
    errorMessage = prx.SubmitToQueue(firstName, lastName);
    return errorMessage;
  }

Now open the code-behind for the form. Look for the btnAddToQueue_Click event handler. Change this:

string errorMessage = string.Empty; // DAC.AddToQueue(txtFirstName.Text, txtLastName.Text);

to this:

string errorMessage = DAC.AddToQueue(txtFirstName.Text, txtLastName.Text);

Run the client application. Click on GetCustomerList to see your list of customers. Now fill in the first and last name of one of your customers and cliick the AddToQueue button. Try a couple of them.

We haven’t written anything to process the messages, so they will sit on the queue for a week before they are automatically removed. If I open Cerebrata Cloud Storage Studio and look at the queue in my development storage, I can see the messages:

In my next post, I’ll show you how to set up the worker role and read the messages and write the information to blob storage.

Tags:

One Response to “Azure for Developers Tutorial Step 5: Adding messages to a queue”

  1. Azure for Developers: Introduction to the Tutorial | RobinDotNet's Blog Says:

    […] Step 5: Adding messages to a queue […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: