Now that you have an understanding of the idea behind the Cloud Storage API it’s time to show it in action. We will start by writing a simple application accessing the Message Queue using the API.
Note: Premier time for a guest blogger at Techie.notepad! WooHoo! Peter von Lochow is the man behind this post.
The implementation we use for the API is developed against Azure but the API should be reusable for any type of Cloud. While doing this our main goals (just to reiterate) are:
- Enable testability
- Abstract away storage
- Extensible and easy to evolve during development
This is the first of three posts showing functionality of the API. The other two will explain in a similar fashion how to use the Blob Storage and Entity Storage.
Here are the other posts in this series:
Now, as this is my first blog post, ever, please have patience with my high school English and poorly formed sentences. The idea is to give a short introduction to our solution for the Queue Service and show some code examples on how our API can be used to simplify testing in your applications and thus generally improve your life as a cloud developer.
Overview
To give some context to the code you will see, here is a screenshot of the kickass end result. ;-)
What this application does is read the input from the TextBox and put it in a Cloud Storage Queue. You can send several messages and the retrieve them in a FIFO fashion by pushing the get button. As I said it’s a very simple example, but it is fine for showing how you can use the API.
Let’s start with the tests
Testability is a very important reason for us doing this. Therefore the logic for this application is not handled in the code behind of the page but rather in a separate controller that the page will call. Let’s name it DefaultController (yes, my imagination is really that poor). We could also have used an ASP.NET MVC application here but that’s really besides the point of this exercise. Since it should take care of operations made on the Queue we put an IQueueDataContext (which is a part of the CloudStorage.API) parameter in the constructor. We’ll follow the naming convention of MethodName_StateUnderTest_ExpectedBehavior and start writing.
[TestInitialize]
public void TestInitialize()
{
_queueDataContext = MockRepository.GenerateStub<IQueueDataContext>();
_queueDataContext.Stub(x => x.PutMessage(string.Empty));
_defaultController = new DefaultController(_queueDataContext);
}
[TestMethod]
public void PutMessage_WhenMessageIsEmpty_ShouldIgnoreMessage()
{
string emptyMessage = string.Empty;
_defaultController.PutMessage(emptyMessage);
_queueDataContext.AssertWasNotCalled(x => x.PutMessage(emptyMessage));
}
[TestMethod]
public void PutMessage_WhenMessageContainsText_ShouldPutMessage()
{
string messageWithText = "Message!";
_defaultController.PutMessage(messageWithText);
_queueDataContext.AssertWasCalled(x => x.PutMessage(messageWithText));
}
Tada, we got our first tests! We won’t bore you with writing test after test for each of the methods and aim for full coverage; you probably get the point by now.
Let the coding begin
By using ReSharper or just basic functionality in VS2008 we came up with the following basic Controller class.
private readonly IQueueDataContext _queueDataContext;
public DefaultController(IQueueDataContext queueDataContext)
{
_queueDataContext = queueDataContext;
}
Let’s start by adding our PutMessage method.
public void PutMessage(string message)
{
if (string.IsNullOrEmpty(message)) return;
_queueDataContext.PutMessage(message);
}
This method should satisfy our tests. Now in the same fashion I add the two following methods for retrieving the messages in the Queue and checking if the Queue is empty.
public string GetMessageAsString()
{
return QueueIsEmpty() ?
"No Message in Queue" :
_queueDataContext.GetMessages(1).Single().MessageText;
}
public bool QueueIsEmpty()
{
return _queueDataContext.PeekMessages(1).SingleOrDefault() == null;
}
public int NumberOfMessagesInQueue()
{
var queueMetadata = _queueDataContext.GetQueueMetadata();
return queueMetadata.ApproximateMessageCount;
}
Note: Notice the method calls for GetMessages and PeekMessages. They are called with a parameter (int numberOfMessages) which tells the method how many messages it should retrieve. Instead of writing a method GetMessage/PeekMessage we intentionally limited the API to only have a single method with a parameter for retrieving messages. The only reason for this was to better match the REST API. We didn’t want to make any assumptions on what functionality a developer may want out of the API. By matching the REST API as far as possible we leave it up to the developer to form the functionality as he/she sees fit.
We have however implemented an extension method .GetMessage() that wraps the .GetMessages(1) function call and returns one message.
Putting the Controller to use
All we have to do now is add the controller behind the code behind for the aspx-page. Instead of sending in our mock interface we use the real deal and get:
protected void Page_Load(object sender, EventArgs e)
{
var context = CloudStorageDataContextFactory.GetCloudStorageQueue("messageQueue");
_defaultController = new DefaultController(context);
DisplayNumberOfMessagesInQueue();
}
private void DisplayNumberOfMessagesInQueue()
{
QueuedMessagesLabel.Text = string.Format("Messages in Queue {0}.", _defaultController.NumberOfMessagesInQueue());
}
protected void SendMessageButton_OnClick(object sender, EventArgs e)
{
_defaultController.PutMessage(MessageTextBox.Text);
}
protected void RetrieveMessageButton_OnClick(object sender, EventArgs e)
{
MessageLabel.Text = _defaultController.GetMessageAsString();
}
We use our partial implementation of the API to fetch an instance of IQueueDataContext. The ICloudStorageDataContextFactory exposes a method which we can use to get started, namely the .GetCloudStorageQueue(string queueName)-method. It can either take the name of the Queue or an instance of the IStorageAccountInfo and a Queue name as parameters. In our example we’ll be satisfied with only providing a name and use the default account specified in a configuration file.
That’s it!
This should give you a glimpse of how we envisioned the Cloud Storage API for queues. You can simplify calls made to a Cloud Service as well as enabling testing and decoupling. Magnus and I will push to upload the implementation on Azure Contrib so that you can take it out for a spin. All feedback is welcome! :-)
/ P
P.S.: I would really like to thank Magnus for taking a chance at lowering the quality of a great blog by letting me be a guest writer. It has been a pleasure writing the API, hope you’ll like it!
posted @ Monday, August 17, 2009 3:51 PM