Using Windows Azure Service Bus from Ruby Apps

This article provides information on working with the Windows Azure AppFabric Service Bus from the Ruby programming language. This article assumes that you are familiar with Ruby, and have access to the Windows Azure AppFabric labs site (AppFabricLabs.com.) For more information on Ruby, see ruby-lang.org.

Introduction

Using Azure AppFabric Service Bus Queues from Ruby is easy. However, it’s not as easy to get started using as it should be because most of the guidance available is written for .NET developers using the .NET libraries provided with the Windows Azure AppFabric SDK. While there are packages for using Windows Azure Storage from Ruby (WAZ-Storage), there’s currently no equivalent for the AppFabric Service Bus. In addition, the AppFabric Queues May CTP requires authentication via ACS v2, for which there is also currently no library.

Sure, for both the basics are building a REST client, but when it comes to the details such as what Ruby packages to use to communicate in ways that mimic what is done in the .NET samples, things may become more confusing than they need to be, primarily owing to a lack of documentation on this.

This blog will walk thru the high level pieces you need in order to leverage AppFabric Queues from Ruby. We will focus on leveraging Queues directly, but provide a complete library that includes support for Topics and Subscriptions (as well as code samples that show how to use them from Ruby).

We will also show how to implement a client in Ruby; the steps taken serve to illustrate what one would need to perform from other non-.NET languages which offer a REST enabled client – we intentionally try to keep the Ruby specifics to a minimum and emphasize the more universal REST aspects.

Example Scenario – A Simple Rails App

To drive the implementation, let’s think through a simple scenario that would be common for a Ruby on Rails application (see the figure below). Let’s say we have a web page that takes some input representing work to be performed and pushes it to an AppFabric Queue. A backend process pulls the enqueued item from the queue and processes it. In this blog, we show how you would build the communication for both sending messages to the queue from the web app and retrieving messages from the queue from within the worker process.

Want to Play Along?

Before we dive in, feel free to set yourself to follow along with the sample code, we won’t show too much code in the blog in an effort to emphasize the approach, but the sample contains the complete code. If you are a .NET developer programming in Visual Studio 2010, Ruby may be unfamiliar- but the setup is easy and we encourage you to try out the provided sample code. If you are an experienced Ruby developer, you can skip over the first of the setup steps and directly go to downloading and running the code (Steps 3 and 4).

Quick Environment Setup

  1. Ensure you have created your AppFabric ServiceBus namespace. Follow the instructions here.
  2. Download and Install Ruby 1.8.7. We suggest getting a distribution from RubyInstaller.org
  3. Next, install the Rails-Client gem (a gem is like an assembly or library). This gem provides a handy REST enabled Client that is used by the source code we provide to interact with the ACS and AppFabric Queue services. To install it, after installing Ruby, fire up a command prompt and run the following command:

    gem install rest-client

  4. The sample code as stand-alone Ruby files or the IronRuby (see the notes for additional information) project are available with this publication for download. .
  5. Open Program.rb and set your service namespace, service identity name and service identity password at the top, based on the values you acquired after setting up your namespace.
  6. Run the code by opening a command prompt (cmd.exe,) and navigating to the directory where you extracted the sample code, and then execute the following command:

    ruby Program.rb
  7. You should see output similar to the following:

    Using scope URI of http://RubyQueue.servicebus.appfabriclabs.com

    Authenticating via ACS

    net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.micros

    oft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%

    2f%2fRubyQueue-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2fRubyQ

    ueue.servicebus.appfabriclabs.com&ExpiresOn=1308769516&Issuer=https%3a%2f%2fruby

    queue-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=RqUmM7TYUd3KuA44V7n%2bOHV

    dNTaQC11nmfOnubxwH8s%3d

    Queue Management – Create Queue

    ……….

Overview of the Sample Code

The sample library has a handful of files providing support for Queues, Topics and Subscriptions. For this blog we will focus on these 4 ruby files that provide support for Queues:

  • Under the WAZ\AppFabric\ folder
    • AccessControl.rb – helper library for using ACS v2 from Ruby to acquire Simple Web Tokens used in communicating with Queues.
    • QueueClient.rb – helper library for sending messages to and receiving messages from Azure AppFabric Queues May 2011 CTP.
    • QueueManagement.rb – helper library for creating, enumerating and deleting Queues with the Azure AppFabric Queues May 2011 CTP.
    • Note 1: There are no hard coded paths in Program.rb. This folder structure is how Ruby deals with namespaces.
    • Note 2: The sample code is not repackaged as a GEM…since it’s not a library per se, but rather sample code that could become a good library.

       

  • Program.rb – a simple console application that walks thru all operations you might want to perform with Queues using REST:
    • Authenticating with ACS to get a Simple Web Token
    • Creating a new Queue
    • Getting a single Queue Description
    • Enumerating all Queues
    • Sending a message to a Queue
    • Atomically receiving and deleting the message
    • Peek lock receiving a message
    • Unlocking a peek-locked message
    • Deleting a peek-locked message
    • Deleting a Queue
    • How to enable communication inspection with Fiddler by configuring the proxy

Note that the sample library is focused on using simple Queues and does not demonstrate how to use Topics or Subscriptions (though it is readily extended to this).

Sidebar – What about IronRuby?

IronRuby 1.1.3 provides Visual Studio integration for Ruby 1.9.2, but it does not implement the complete Ruby specification- and the limitations prevent running our sample code. You can, however, benefit from the syntax coloring and project templates by installing IronRuby and using it to edit your code or to read thru the samples we provide– just be sure to run your code using a more complete Ruby interpreter (like the one from RubyInstaller.org). An interesting aside, if you prefer to use IronRuby, you *could* theoretically use the .NET client assemblies for the Service Bus (as IronRuby enables you to call .NET code from Ruby), so you would probably not use the Rest Client we demonstrate here. For convenience, we include the sample code as an IronRuby project as well.

Sidebar – Can you run Ruby within Windows Azure?

What’s more, if you want to cloud host this code (or any Ruby on Rails application) you are completely able to within a Windows Azure Worker Role. I do plan to provide the sample code in a future blog, for now I list out the general steps below:

  1. Create a Visual Studio Cloud Project
  2. Include the Rails Application & Ruby Runtime Binaries in the Role (or install the runtime with a startup task)
  3. Create RoleEntryPoint that launches a Process which executes the ruby program or web server (like WEBrick) and keeps it alive (it can simply periodically check if the process is still running).
  4. Configure input endpoints to map to the ports on which the web server (e.g., WEBrick) is listening.

The link http://archive.msdn.microsoft.com/railsonazure has some additional details around this.

Send and Receive Communication

Let’s take a closer look at how communication actually happens in order for both the Ruby on Rails web application and the worker process to communicate with the Service Bus Queue in the manner described in the over view. The AppFabric Queues offer two approaches for receiving data from a Queue: one that retrieves and deletes the messages in a single operation and another that that enables you to lock a message and decide later whether to delete it or return it to the queue. We will look at both but begin by looking at the simpler case which retrieves and deletes a message from the queue as a single operation as shown in the figure below. The details of each step will be described in the sections that follow.

 

 

  1. ACS is the security mechanism for controlling interaction with the Service Bus. The Ruby logic running within the Rails web app needs to acquire an Access Token from the AppFabric Access Control service in order to use the Service Bus.
  2. ACS returns the token in the form of a Simple Web Token within the body of the response.
  3. The Ruby logic needs to extract just the WRAP SWT from the response and place it in the Authorization header when making a POST against the Queue. The payload of the message is wrapped in an entry and sent as the body of the POST.
  4. If successful, the Queue returns a 201 Created status code.
  5. Meanwhile, the Worker Process running some Ruby code also needs to request an access token from ACS.
  6. ACS provides the SWT in the same way as before.
  7. To retrieve and delete a message as an atomic operation, the worker process sends a DELETE request to the Queue, including the access token in the authorization header.
  8. When a message is present, a response with a code of 200 OK is returned, along with a body that contains the entry payload. The worker process can then take action on this message, which is no longer present in the queue.

Let’s take a look at the details behind this pattern of communication, starting with the authentication with ACS.

Authenticating via ACS

Before you can make your first call against AppFabric Queues, you will need to be able to authenticate with ACS. Let’s take a look at what it takes to perform some basic authentication with ACS using Ruby. The approach is to use ACS’s support for Simple Web Tokens.

This amounts to constructing a request that looks like the following:

Sample ACS Token Request

 

POST https://rubytest-sb.accesscontrol.appfabriclabs.com/WRAPv0.9/ HTTP/1.1

Accept: */*; q=0.5, application/xml

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

Content-Length: 140

Host: rubytest-sb.accesscontrol.appfabriclabs.com

 

wrap_name=owner&wrap_password=xwCOTgOHT%2Fw8daI9mhCA8Vm0SlKYPKZojYfYCafsRaU%3D&wrap_scope=http%3A%2F%2Frubytest.servicebus.appfabriclabs.com

 

Within this request the key items are to:

  1. Use a POST verb
  2. Set the Content-Type header to:
    application/x-www-form-urlencoded
  3. Target the WRAP endpoint of ACS, at:

    https://{serviceNamespace}-sb.accesscontrol.appfabriclabs.com/WRAPv0.9/
  4. Include your namespace’s Issuer as the wrap_name in the body
  5. Include your namespace’s Key as wrap_password in the body.
  6. Include your namespace as the wrap_scope in the body.

Next, you need to extract the token from the response. The complete response looks like the following:

Sample ACS Token Response

 

HTTP/1.1 200 OK

Cache-Control: private

Content-Type: application/x-www-form-urlencoded; charset=us-ascii

Server: Microsoft-IIS/7.0

Set-Cookie: ASP.NET_SessionId=sjnd1145ejbpynmkcmtdlj55; path=/; HttpOnly

X-AspNetMvc-Version: 2.0

X-AspNet-Version: 2.0.50727

X-Powered-By: ASP.NET

Date: Mon, 30 May 2011 19:08:48 GMT

Content-Length: 544

 

wrap_access_token=net.windows.servicebus.action%3dListen%252cManage%252cSend%26http%253a%252f%252fschemas.microsoft.com%252faccesscontrolservice%252f2010%252f07%252fclaims%252fidentityprovider%3dhttps%253a%252f%252frubytest-sb.accesscontrol.appfabriclabs.com%252f%26Audience%3dhttp%253a%252f%252frubytest.servicebus.appfabriclabs.com%26ExpiresOn%3d1306783728%26Issuer%3dhttps%253a%252f%252frubytest-sb.accesscontrol.appfabriclabs.com%252f%26HMACSHA256%3d7u4ZYF2M%252fX8qLg2meV2xASQT00np536D6JaSEKjAB%252bI%253d&wrap_access_token_expires_in=1200

 

The value you are after for the access token is only the portion that follows wrap_access_token and does not include the wrap_access_token_expires value. You also have to URL-decode this value. From the previous request, the final decoded SWT value we are after looks like:

net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d

Ruby Code

The Ruby code which implements this request and extracts the token from the response is shown in the complete listing for the AccessControl.rb (shown at the end of this blog). Getting a token from ACS in Ruby, then amounts to making the following calls (from Program.rb):

scopeUri = WAZ::AppFabric::AccessControl.get_scope(serviceNamespace)

accessToken = WAZ::AppFabric::AccessControl.get_access_token(serviceNamespace, scopeUri, serviceIdentityName, serviceIdentityPassword)

 

With this, we have the token necessary to begin communicating with the Queue. Note that these tokens eventually expire, so if you will be caching this value, you may have to build logic to periodically renew the token by repeating the request.

Queue Runtime – Sending Messages

Now the application is ready to send messages to the queue. This amounts to constructing a request that looks like the following:

Sample Send to Queue Request

 

POST https://rubytest.servicebus.appfabriclabs.com/testqueue/messages HTTP/1.1

Accept: */*; q=0.5, application/xml

Content-Type: application/atom+xml;type=entry;charset=utf-8

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 110

Host: rubytest.servicebus.appfabriclabs.com

 

<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’>Hello, from Ruby!</content></entry>

 

Within this request the key steps are to:

  1. Use the POST verb
  2. Set the Content-Type header to:
    application/atom+xml;type=entry;charset=utf-8
  3. Target the queue by name by posting to:

    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}/messages
  4. Include the previously acquired access token in the Authorization header. This has a very particular form for the value which is (note the space after WRAP, it’s not an underscore):
    WRAP access_token=”{access token value}”
  5. The body of the request needs to include the message content in an envelope that looks like the following:
    <entry xmlns=’http://www.w3.org/2005/Atom’>
    <content type=’application/xml’>
    {message content}
    </content>
    </entry>

A successful response to this will take the following form:

Sample Send to Queue Response

 

HTTP/1.1 201 Created

Content-Type: application/xml; charset=utf-8

Server: Microsoft-HTTPAPI/2.0

Date: Mon, 30 May 2011 19:08:59 GMT

Content-Length: 0

 

Ruby Code

The implementation for this is straightforward, consisting of the send, generate_send_request_uri, generate_queue_payload and generate_request as shown in the full listing of QueueClient.rb (provided at the end of this blog). Therefore sending a message to the AppFabric Queue from Ruby simply becomes this (as shown in Program.rb):

 

sendMessageResponse = WAZ::AppFabric::QueueClient.send(serviceNamespace, queueName, accessToken,
‘Hello, from Ruby!’)

Queue Runtime – Receiving Messages

Now that we have a message in the queue, our worker process will need to be able to retrieve it. As we said previously, there are two approaches.

 

Receive & Delete Retrieval

Here we show how to retrieve and delete the message in a single operation. This is accomplished by making a request of the following form:

 

Sample Receive & Delete Request

 

DELETE https://rubytest.servicebus.appfabriclabs.com/testqueue/messages/head?timeout=60 HTTP/1.1

Accept: */*; q=0.5, application/xml

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 0

Host: rubytest.servicebus.appfabriclabs.com

 

The key points to structuring this request are:

  1. Use the DELETE verb
  2. Target the head of the messages in the desired queue by submitting to the following URL. The timeout represents an HTTP long polling feature where the server will hold the request waiting for a message to appear until the specified time elapses. The timeout value is specified as an integer without units (like “30″ for a thirty second timeout).


    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}/messages/head?timeout={time}
  3. Include the previously acquired access token in the Authorization header.

 

A successful response to this will include the next message from the head of the queue and take the following form:

 

Sample Receive & Delete Response

 

HTTP/1.1 200 OK

Content-Type: application/atom+xml;type=entry;charset=utf-8

Server: Microsoft-HTTPAPI/2.0

X-MS-DELIVERY-COUNT: 0

X-MS-LOCKED-UNTIL: Mon, 30 May 2011 19:09:30 GMT

X-MS-MESSAGE-ID: fa42914d3f7b4a8abc8437d29e9a3c03

X-MS-SEQUENCE-NUMBER: 1

X-MS-SIZE: 110

Date: Mon, 30 May 2011 19:08:59 GMT

Content-Length: 110

 

<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’>Hello, from Ruby!</content></entry>

 

Ruby Code

Our sample library shows this approach in Ruby, as implemented by the receive method in QueueClient.rb (shown in the complete listing at the end of this blog). With that in place, using Ruby to retrieve and delete a message looks like the following:

 

receiveMessageResponse = WAZ::AppFabric::QueueClient.receive(serviceNamespace, queueName, accessToken)

 

Peek-Lock Retrieval

Now, let’s look at an alternative approach to retrieving a message, whereby the worker process instead must explicitly delete the message when it has completed its processing. Moreover, it only has a specific window of time (say 30 seconds) in which to delete the message or the Queue automatically makes the message available to another caller (as you might desire in case the worker process that originally acquired the message crashed before completion). If the worker process determines it cannot process the message, it could elect to unlock the message and thereby explicitly release the message back into the queue (perhaps for another attempt). This form of retrieving a message is referred to as a Peek-Lock and completion is signaled by a call to Delete the Peek Locked Message and releasing the message by calling Unlock.

 

Let’s start with the approach for Peek-Lock retrieval. This is a request that takes the form:

Sample Peek-Locked Request

 

POST https://rubytest.servicebus.appfabriclabs.com/testqueue/messages/head?timeout=60 HTTP/1.1

Accept: */*; q=0.5, application/xml

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 0

Host: rubytest.servicebus.appfabriclabs.com

 

Within this request, the key steps are:

  1. Use the POST verb
  2. Target the head of the messages in the desired queue by submitting to the following URL (it’s the same URL used by the Receive and Delete). Again specify a timeout for HTTP long polling:

    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}/messages/head?timeout={time}
  3. Include the previously acquired access token in the Authorization header.

 

A successful request, when a message is present, will return a response similar to the following:

Sample Peek-Locked Response

 

HTTP/1.1 200 OK

Content-Type: application/atom+xml;type=entry;charset=utf-8

Server: Microsoft-HTTPAPI/2.0

X-MS-MESSAGE-LOCATION: https://rubytest.servicebus.appfabriclabs.com/testqueue/Messages/5743357095e34fe59cf8f9d9b16366ea

X-MS-LOCK-ID: 0c23bb07-1ffb-4c9d-89a0-ed7d3df2c71f

X-MS-LOCK-LOCATION: https://rubytest.servicebus.appfabriclabs.com/testqueue/Messages/5743357095e34fe59cf8f9d9b16366ea/0c23bb07-1ffb-4c9d-89a0-ed7d3df2c71f

X-MS-DELIVERY-COUNT: 0

X-MS-LOCKED-UNTIL: Mon, 30 May 2011 19:09:30 GMT

X-MS-MESSAGE-ID: 5743357095e34fe59cf8f9d9b16366ea

X-MS-SEQUENCE-NUMBER: 2

X-MS-SIZE: 110

Date: Mon, 30 May 2011 19:08:59 GMT

Content-Length: 110

 

<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’>Hello, from Ruby!</content></entry>

 

Before you move on to processing the message body, you should capture the values of the X-MS-MESSAGE-ID and X-MS-LOCK-ID headers. Then go ahead and process the message body. When you have completed processing successfully (and want to delete the peek-locked message from the queue), you need to send a request similar to the following:

 

Sample Delete Request

 

DELETE https://rubytest.servicebus.appfabriclabs.com/testqueue/messages/5743357095e34fe59cf8f9d9b16366ea/0c23bb07-1ffb-4c9d-89a0-ed7d3df2c71f HTTP/1.1

Accept: */*; q=0.5, application/xml

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 0

Host: rubytest.servicebus.appfabriclabs.com

 

The key parts to constructing this request are:

  1. Use the DELETE verb
  2. Target the specific message and lock by providing the message id and lock id values captured previously in the request URL:

    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queuePath}/messages/{messageId}?lockId={lockId}
  3. Include the previously acquired access token in the Authorization header.

 

A successful response to this request should be of the form:

Sample Delete Peek-Locked Message Response

 

HTTP/1.1 200 OK

Content-Type: application/xml; charset=utf-8

Server: Microsoft-HTTPAPI/2.0

Date: Mon, 30 May 2011 19:09:00 GMT

Content-Length: 0

 

Ruby Code

The QueueClient.rb with its peekLock and deletePeekedMessage methods implement this logic in Ruby. Using the QueueClient then takes the following pattern (from Program.rb):

 

peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)

messageId = peeklockMessageResponse.headers[:x_ms_message_id]

lockId = peeklockMessageResponse.headers[:x_ms_lock_id]

deletelockedMessageResponse = WAZ::AppFabric::QueueClient.deletePeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)

 

If instead of deleting the message, you wish to unlock it, you must send a request of the form:

Sample Unlock Request

 

DELETE https://rubytest.servicebus.appfabriclabs.com/testqueue/messages/5743357095e34fe59cf8f9d9b16366ea/0c23bb07-1ffb-4c9d-89a0-ed7d3df2c71f HTTP/1.1

Accept: */*; q=0.5, application/xml

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 0

Host: rubytest.servicebus.appfabriclabs.com

 

The key parts to this request are:

  1. Use the DELETE verb
  2. Target a slightly different URL which names both the message id and lock id previously acquired. Notice it includes the lock id in the path instead of as a query parameter as was done for deleting a peek locked message:

    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queuePath}/messages/{messageId}/{lockId}
  3. Include the previously acquired access token in the Authorization header.

 

The successful response to this request is the same (HTTP 200 OK) as that shown for the Delete Peek-Locked Message.

 

Ruby Code

Again, the QueueClient.rb shows the complete Ruby implementation, you would call it as follows (as shown in Program.rb):

 

peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)

messageId = peeklockMessageResponse.headers[:x_ms_message_id]

lockId = peeklockMessageResponse.headers[:x_ms_lock_id]

 

unlockMessageResponse = WAZ::AppFabric::QueueClient.unlockPeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)

 

Queue Management – Creating, Inspecting and Deleting Queues

Beyond enabling run-time operations, the REST API to the Service Bus Queues also enables you to create, delete and inspect queue metadata. Given what we’ve already shown how to use the runtime operations, using these features will appear as old-hat. Requests need to first acquire an access token from ACS and then call the appropriate method. Let’s take a look at these.

Creating Queues

If a purely non-.NET scenario, someone would need to create the queue for our web app or worker process to use.

Creating a queue is performed by building a request as follows:

Sample Creating a Queue Request

 

PUT https://rubytest.servicebus.appfabriclabs.com/testqueue HTTP/1.1

Accept: */*; q=0.5, application/xml

Content-Type: application/atom+xml;type=entry;charset=utf-8

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 693

Host: rubytest.servicebus.appfabriclabs.com

 

<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’><QueueDescription xmlns:i=”http://www.w3.org/2001/XMLSchema-instance” xmlns=”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect”> <LockDuration>PT30S</LockDuration> <MaxQueueSizeInBytes>104857600</MaxQueueSizeInBytes> <RequiresDuplicateDetection>false</RequiresDuplicateDetection> <RequiresSession>false</RequiresSession> <DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive> <DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration> <DuplicateDetectionHistoryTimeWindow>PT10M</DuplicateDetectionHistoryTimeWindow></QueueDescription></content></entry>

 

The key parts to creating a new Queue request are:

  1. Use the PUT verb
  2. Target a URL that includes the namespace and name of the queue you wish to create.

    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queuePath}
  3. Include the previously acquired access token in the Authorization header.
  4. Set the Content-Type to

    application/atom+xml;type=entry;charset=utf-8
  5. Send a queue description in the body of the message. A queue description has the form (see the MSDN documentation for details on each field):

    <entry xmlns=’http://www.w3.org/2005/Atom’>
    <content type=’application/xml’>
    <QueueDescription xmlns:i=\”http://www.w3.org/2001/XMLSchema-instance\” xmlns=\”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect\”>
    <LockDuration>PT30S</LockDuration>
    <MaxQueueSizeInBytes>104857600</MaxQueueSizeInBytes>
    <RequiresDuplicateDetection>false</RequiresDuplicateDetection>
    <RequiresSession>false</RequiresSession>
    <DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive>
    <DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration>
    <DuplicateDetectionHistoryTimeWindow>PT10M</DuplicateDetectionHistoryTimeWindow>
    </QueueDescription>
    </content>
    </entry>

     

Ruby Code

The logic for queue management is within the QueueManagement.rb file, and create_queue is the method which can be called to create the new Queue. For example, creating a new queue looks as follows in Ruby:

 

createQueueResponse = WAZ::AppFabric::QueueManagement.create_queue(serviceNamespace, queueName, accessToken)

 

Queue Descriptions & Enumerating Queues

Once a queue is created, the queue descriptions can be retrieved later. This can be useful to verify configuration or to see the values applied to queues created using default settings.

A request for a particular queue within a namespace is built to the form:

Sample Getting a Queue Description Request

 

GET https://rubytest.servicebus.appfabriclabs.com/testqueue HTTP/1.1

Accept: */*; q=0.5, application/xml

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 0

Host: rubytest.servicebus.appfabriclabs.com

 

The key parts to this request are:

  1. Use the GET verb
  2. Target the queue by name:

    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}
  3. Include the previously acquired access token in the Authorization header.

 

The successful response to this takes the form (notice the queue description in the response body):

Sample Getting a Queue Description Response

 

HTTP/1.1 200 OK

Content-Type: application/atom+xml;type=entry;charset=utf-8

Server: Microsoft-HTTPAPI/2.0

Date: Mon, 30 May 2011 19:08:59 GMT

Content-Length: 980

 

<entry xmlns=”http://www.w3.org/2005/Atom”><id>https://rubytest.servicebus.appfabriclabs.com/testqueue</id><title type=”text”>testqueue</title><published>2011-05-30T19:08:58Z</published><updated>2011-05-30T19:08:58Z</updated><author><name>rubytest</name></author><link rel=”self” href=”https://rubytest.servicebus.appfabriclabs.com/testqueue”/><content type=”application/xml”><QueueDescription xmlns=”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance”><LockDuration>PT30S</LockDuration><MaxQueueSizeInBytes>104857600</MaxQueueSizeInBytes><RequiresDuplicateDetection>false</RequiresDuplicateDetection><RequiresSession>false</RequiresSession><DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive><DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration><DuplicateDetectionHistoryTimeWindow>PT10M</DuplicateDetectionHistoryTimeWindow></QueueDescription></content></entry>

 

Similarly, a list of descriptions for all queues at a certain point in the namespace’s hierarchy can be achieved with:

Sample Enumerating All Queue Descriptions Request

 

GET https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues HTTP/1.1

Accept: */*; q=0.5, application/xml

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 0

Host: rubytest.servicebus.appfabriclabs.com

 

The key parts to this request are:

  1. Use the GET verb
  2. Target the special $Resources/Queues path

    https://{serviceNamespace}.servicebus.appfabriclabs.com/$Resources/Queues
  3. Include the previously acquired access token in the Authorization header.

     

The successful response to this contains all the queue descriptions for that level in the namespace hierarchy:

Sample Enumerating All Queue Descriptions Response

 

HTTP/1.1 200 OK

Content-Type: application/atom+xml;type=feed;charset=utf-8

Server: Microsoft-HTTPAPI/2.0

Date: Mon, 30 May 2011 19:08:59 GMT

Content-Length: 1258

 

<feed xmlns=”http://www.w3.org/2005/Atom”><title type=”text”>Queues</title><id>https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues</id><updated>2011-05-30T19:08:59Z</updated><link rel=”self” href=”https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues”/><entry xml:base=”https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues”><id>https://rubytest.servicebus.appfabriclabs.com/testqueue</id><title type=”text”>testqueue</title><published>2011-05-30T19:08:58Z</published><updated>2011-05-30T19:08:58Z</updated><author><name>rubytest</name></author><link rel=”self” href=”../testqueue”/><content type=”application/xml”><QueueDescription xmlns=”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance”><LockDuration>PT30S</LockDuration><MaxQueueSizeInBytes>104857600</MaxQueueSizeInBytes><RequiresDuplicateDetection>false</RequiresDuplicateDetection><RequiresSession>false</RequiresSession><DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive><DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration><DuplicateDetectionHistoryTimeWindow>PT10M</DuplicateDetectionHistoryTimeWindow></QueueDescription></content></entry></feed>

 

Ruby Code

Within QueueManagement.rb, this logic is exposed by the get_queue and list_queues methods. Their use is as follows:

getQueueResponse = WAZ::AppFabric::QueueManagement.get_queue(serviceNamespace, queueName, accessToken)

 

listQueuesResponse = WAZ::AppFabric::QueueManagement.list_queues(serviceNamespace, accessToken)

 

Deleting Queues

There are limits to the number of queues that you can create, and one way to manage that is to delete unused queues.

You delete a queue by creating a request with the following structure:

Sample Delete Queue Request

 

DELETE https://rubytest.servicebus.appfabriclabs.com/testqueue HTTP/1.1

Accept: */*; q=0.5, application/xml

Accept-Encoding: gzip, deflate

Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”

Content-Length: 0

Host: rubytest.servicebus.appfabriclabs.com

 

The key parts to constructing this request are:

  1. Use the DELETE verb
  2. Target the queue by namespace and queue name:

    https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}
  3. Include the previously acquired access token in the Authorization header.

 

The successful response to this request is the same (HTTP 200 OK) as that shown for the Delete Peek-Locked Message.

 

Ruby Code

Within QueueManagement.rb, this logic is exposed by the delete_queue method and is used as follows:

deleteQueueResponse = WAZ::AppFabric::QueueManagement.delete_queue(serviceNamespace, queueName, accessToken)

Limitations to using REST Clients with Service Bus Queues

Compared to using the AppFabric Service Bus with the .NET client provided by the Azure AppFabric SDK, a REST client has some limitations (in the current CTP form) that apply to more advanced features. For the purposes of sending to and receiving from Queues, Topics or Subscriptions the REST API are simple, powerful and all you need. For details on the specific limitations, see the documentation.

Examining Communication with Fiddler

The source code of Program.rb contains the following line commented out:

###### OPTIONAL: Enable the Fiddler Proxy (if running Fiddler) #########

#RestClient.proxy = “http://127.0.0.1:9999/”

#########################################################################


If you want to use Fiddler debugging proxy to monitor HTTP traffic between your local Ruby application and the AppFabric Queues or ACS, start by installing Fiddler from http://www.fiddler2.com/fiddler2/ and configure the port to listen on in the Fiddler Options (as shown in the screenshot below).

After setting the port, uncomment the RestClient.proxy line in Program.rb and set the port value. For example, if the port is 9999, then the code would look like:

###### OPTIONAL: Enable the Fiddler Proxy (if running Fiddler) #########

RestClient.proxy = “http://127.0.0.1:9999/”

#########################################################################

 

Note: Port 9999 is more convenient for .NET developers running Azure emulator so that it and Fiddler don’t conflict.

Ruby Source Code

The complete listing for the sample client application in Program.rb and the three files that make up the Queue client library are provided below.

Program.rb

 

require ‘rubygems’

require ‘rest-client’

require ‘WAZ/AppFabric/AccessControl’

require ‘WAZ/AppFabric/QueueManagement’

require ‘WAZ/AppFabric/QueueClient’

 

###### ENTER YOUR QUEUE SETTINGS HERE ###################################

serviceNamespace =
“rubytest”

queueName =
‘testqueue’

serviceIdentityName =
“owner”

serviceIdentityPassword =
“xwCOTgOHT/w8daI9mhCA8Vm0SlKYPKZojYfYCafsRaU=”

#########################################################################

 

 

###### OPTIONAL: Enable the Fiddler Proxy (if runnning Fiddler) #########

#RestClient.proxy = “http://127.0.0.1:9999/”

#########################################################################

 

scopeUri = WAZ::AppFabric::AccessControl.get_scope(serviceNamespace)

puts ‘Using scope URI of ‘
+ scopeUri

 

puts ‘Authenticating via ACS’

accessToken = WAZ::AppFabric::AccessControl.get_access_token(serviceNamespace, scopeUri, serviceIdentityName, serviceIdentityPassword)

puts accessToken

 

puts ‘Queue Management – Create Queue’

createQueueResponse = WAZ::AppFabric::QueueManagement.create_queue(serviceNamespace, queueName, accessToken)

puts createQueueResponse

 

puts ‘Queue Management – Get Queue’

getQueueResponse = WAZ::AppFabric::QueueManagement.get_queue(serviceNamespace, queueName, accessToken)

puts getQueueResponse

 

puts ‘Queue Management – List Queues’

listQueuesResponse = WAZ::AppFabric::QueueManagement.list_queues(serviceNamespace, accessToken)

puts listQueuesResponse

 

puts ‘Queue Runtime – Sending Messages’

sendMessageResponse = WAZ::AppFabric::QueueClient.send(serviceNamespace, queueName, accessToken,
‘Hello, from Ruby!’)

puts sendMessageResponse

 

puts ‘Queue Runtime – Receiving Messages’

receiveMessageResponse = WAZ::AppFabric::QueueClient.receive(serviceNamespace, queueName, accessToken)

puts receiveMessageResponse

 

puts ‘Queue Runtime – Sending Messages [Again]‘

sendMessageResponse = WAZ::AppFabric::QueueClient.send(serviceNamespace, queueName, accessToken,
‘Hello, from Ruby!’)

puts sendMessageResponse

 

puts ‘Queue Runtime – Peek-Locking Messages’

peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)

p peeklockMessageResponse.headers

messageId = peeklockMessageResponse.headers[:x_ms_message_id]

lockId = peeklockMessageResponse.headers[:x_ms_lock_id]

 

puts ‘Queue Runtime – Unlock-Peeked Messages’

unlockMessageResponse = WAZ::AppFabric::QueueClient.unlockPeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)

p unlockMessageResponse

 

puts ‘Queue Runtime – Peek-Locking Messages [Again]‘

peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)

p peeklockMessageResponse.headers

messageId = peeklockMessageResponse.headers[:x_ms_message_id]

lockId = peeklockMessageResponse.headers[:x_ms_lock_id]

 

puts ‘Queue Runtime – Delete-Peeked Messages’

deletelockedMessageResponse = WAZ::AppFabric::QueueClient.deletePeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)

p deletelockedMessageResponse

 

puts ‘Queue Management – Delete Queue’

deleteQueueResponse = WAZ::AppFabric::QueueManagement.delete_queue(serviceNamespace, queueName, accessToken)

puts deleteQueueResponse

 

AccessControl.rb

 

module WAZ


module AppFabric


class AccessControl


def
self.get_access_token(serviceNamespace, scopeUri, serviceIdentityName, serviceIdentityPassword)

url = generate_request_uri(serviceNamespace)

request = generate_request(:post, url, scopeUri, serviceIdentityName, serviceIdentityPassword)

result = request.execute()


/wrap_access_token=(.+)&/
=~ result


return CGI.unescape(Regexp.last_match[1])


end

 


def
self.get_scope(serviceNamespace)


return
“http://#{serviceNamespace}.servicebus.appfabriclabs.com”


end

 


#############################################################


# private methods

private

 


def
self.generate_request_uri(serviceNamespace)


#url must include WRAP path or will be redirected to broken page


return
“https://#{serviceNamespace}-sb.accesscontrol.appfabriclabs.com/WRAPv0.9/”


end

 


def
self.generate_request(verb, url, scopeUri, serviceIdentityName, serviceIdentityPassword)

payload =
“wrap_name=#{CGI.escape(serviceIdentityName)}&wrap_password=#{CGI.escape(serviceIdentityPassword)}&wrap_scope=#{CGI.escape(scopeUri)}

http_headers =
{}

http_headers.merge!(“Content-Type”
=>
“application/x-www-form-urlencoded”)

http_headers.merge!(“Content-Length”
=>
(payload or
“”).size)

request =
{:headers => http_headers, :method => verb.to_s.downcase.to_sym, :url => url, :payload => payload}


return RestClient::Request.new(request)


end

 


end


end

end

 

QueueClient.rb

 

module WAZ


module AppFabric


class QueueClient


def
self.send(serviceNamespace, queueName, accessToken, content)

url = generate_send_request_uri(serviceNamespace, queueName)

contentType =
“application/atom+xml;type=entry;charset=utf-8″

payload = generate_queue_payload(content);

puts payload

request = generate_request(:post, url, accessToken, contentType, payload)

result = request.execute()


return result


end

 


def
self.receive(serviceNamespace, queueName, accessToken)

url = generate_receive_request_uri(serviceNamespace, queueName,
“60″)

request = generate_request(:delete, url, accessToken,
nil,
nil)

result = request.execute()


return result


end

 


def
self.peeklock(serviceNamespace, queueName, accessToken)

url = generate_receive_request_uri(serviceNamespace, queueName,
“60″)

request = generate_request(:post, url, accessToken,
nil,
nil)

result = request.execute()


return result


end

 


def
self.deletePeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)

url = generate_deletePeekedMessage_request_uri(serviceNamespace, queueName, messageId, lockId)

request = generate_request(:delete, url, accessToken,
nil,
nil)

result = request.execute()


return result


end

 


def
self.unlockPeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)

url = generate_unlockMessage_request_uri(serviceNamespace, queueName, messageId, lockId)

request = generate_request(:delete, url, accessToken,
nil,
nil)

result = request.execute()


return result


end

 


#############################################################


# private methods

private

 


def
self.generate_send_request_uri(serviceNamespace, queuePath)


return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages”


end

 


def
self.generate_receive_request_uri(serviceNamespace, queuePath, timeout)


return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages/head?timeout=#{timeout}


end

 


def
self.generate_deletePeekedMessage_request_uri(serviceNamespace, queuePath, messageId, lockId)


return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages/#{messageId}?lockId=#{lockId}


end

 


def
self.generate_unlockMessage_request_uri(serviceNamespace, queuePath, messageId, lockId)


return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages/#{messageId}/#{lockId}


end

 


def
self.generate_queue_payload(content)


return
“<entry xmlns=’http://www.w3.org/2005/Atom’>”
+


“<content type=’application/xml’>”
+

content +


“</content>”
+


“</entry>”


end

 


def
self.generate_request(verb, url, token, contentType, payload)

authHeaderValue =
“WRAP access_token=\”#{token}\”"

http_headers =
{}

http_headers.merge!(“Authorization”
=> authHeaderValue)


if
(contentType)

http_headers.merge!(“Content-Type”
=> contentType)


end

http_headers.merge!(“Content-Length”
=>
(payload or
“”).size)

request =
{:headers => http_headers, :method => verb.to_s.downcase.to_sym, :url => url, :payload => payload}


return RestClient::Request.new(request)


end

 


end


end

end

 

QueueManagement.rb

 

module WAZ


module AppFabric


class QueueManagement


def
self.create_queue(serviceNamespace, queueName, accessToken)

url = generate_request_uri(serviceNamespace, queueName)

payload = generate_queue_description();

contentType =
“application/atom+xml;type=entry;charset=utf-8″

request = generate_request(:put, url, accessToken, contentType, payload)

result = request.execute()


return result


end

 


def
self.delete_queue(serviceNamespace, queueName, accessToken)

url = generate_request_uri(serviceNamespace, queueName)

request = generate_request(:delete, url, accessToken,
nil,
nil)

result = request.execute()


return result


end

 


def
self.get_queue(serviceNamespace, queueName, accessToken)

url = generate_request_uri(serviceNamespace, queueName)

request = generate_request(:get, url, accessToken,
nil,
nil)

result = request.execute()


return result


end

 


def
self.list_queues(serviceNamespace, accessToken)

url = generate_list_request_uri(serviceNamespace)

request = generate_request(:get, url, accessToken,
nil,
nil)

result = request.execute()


return result


end

 


#############################################################


# private methods

private

 


def
self.generate_request_uri(serviceNamespace, queuePath)


return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}


end

 


def
self.generate_list_request_uri(serviceNamespace)


return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/$Resources/Queues”


end

 


def
self.generate_queue_description()


return
“<entry xmlns=’http://www.w3.org/2005/Atom’>”
+


“<content type=’application/xml’>”
+


“<QueueDescription xmlns:i=\”http://www.w3.org/2001/XMLSchema-instance\” xmlns=\”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect\”>”
+


” <LockDuration>PT30S</LockDuration>”
+


” <MaxQueueSizeInBytes>104857600</MaxQueueSizeInBytes>”
+


” <RequiresDuplicateDetection>false</RequiresDuplicateDetection>”
+


” <RequiresSession>false</RequiresSession>”
+


” <DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive>”
+


” <DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration>”
+


” <DuplicateDetectionHistoryTimeWindow>PT10M</DuplicateDetectionHistoryTimeWindow>”
+


“</QueueDescription>”
+


“</content>”
+


“</entry>”


end

 


def
self.generate_request(verb, url, token, contentType, payload)

authHeaderValue =
“WRAP access_token=\”#{token}\”"

http_headers =
{}

http_headers.merge!(“Authorization”
=> authHeaderValue)


if
(contentType)

http_headers.merge!(“Content-Type”
=> contentType)


end

http_headers.merge!(“Content-Length”
=>
(payload or
“”).size)

request =
{:headers => http_headers, :method => verb.to_s.downcase.to_sym, :url => url, :payload => payload}


return RestClient::Request.new(request)


end

 


end


end

end

 

 

Sample Code

Available for download from here:

  1. Stand-alone Ruby files
  2. IronRuby

Conclusion

The blog article shows how to access Service Bus Queues from Ruby using the sample. Additionally the article also provides information on obtaining authentication tokens from Windows Azure AppFabric ACS, as operations against the AppFabric Service Bus require authentication.

Acknowledgements

Significant contributions of Manuel Ocampo, Larry Franks, Tim Wieman, Valery Mizonov and Zoiner Tejada are acknowledged.

नमस्ते (Namaste)!

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 4.00 out of 5)

One Comment

  1. Pingback: Windows Azure and Cloud Computing Posts for 7/11/2011+ - Windows Azure Blog

Leave a Reply