Page 1 Hands-On Lab Introduction to the Windows Azure AppFabric Service Bus Futures Lab version: 1.0.0 Last updated: 11/16/2010
Page 1
Hands-On Lab
Introduction to the Windows Azure AppFabric Service Bus Futures
Lab version: 1.0.0
Last updated: 11/16/2010
Page 2
CONTENTS
OVERVIEW ................................................................................................................................................... 3
GETTING STARTED: CREATING A SERVICE PROJECT ........................................................................ 5 Task 1 – Provisioning the Service Bus Namespace ............................................................................... 5
EXERCISE 1: SERVICE BUS MANAGEMENT OPERATIONS .................................................................. 8 Task 1 – Adding Operations to Create, List and Delete Connection Points .......................................... 9
Task 2 – Setting Account Information ................................................................................................. 11
Verification .......................................................................................................................................... 12
EXERCISE 2: SERVICE BUS LOAD BALANCING .................................................................................. 15 Task 1 – Creating the Service .............................................................................................................. 15
Task 2 – Creating the Client ................................................................................................................ 18
Task 3 – Setting Account Information ................................................................................................. 22
Verification .......................................................................................................................................... 23
EXERCISE 3: DURABLE MESSAGE BUFFERS ...................................................................................... 28 Task 1 – Implementing Basic Operations with Message Buffers ........................................................ 28
Task 2 – Setting Account Information ................................................................................................. 33
Verification .......................................................................................................................................... 33
SUMMARY .................................................................................................................................................. 40
Page 3
Overview
The Windows Azure AppFabric Service Bus provides secure messaging and connectivity capabilities for
building distributed and disconnected applications in the cloud. In this lab, learn about the new
Windows Azure AppFabric Service Bus capabilities that are now available in the AppFabric LABS. You
will use the management service to manage your connection points and the Anycast feature to load
balance across different instances of a service. Use Message Buffers for basic asynchronous message
processing. These capabilities are part of the incremental updates available as part of new Service Bus
Futures.
Objectives
In this hands-on lab, you will learn how to:
Provision an AppFabric project and create a service namespace.
Use the Windows Azure AppFabric Service Bus management service to manage connection
points.
Use the Anycast feature to load balance across different instances of a service.
Use Durable Message Buffers for asynchronous message processing.
Prerequisites
You must have the following items to complete this lab:
Microsoft Visual Studio 2010
Microsoft.NET Framework 4
Windows Azure platform AppFabric SDK V2.0
Setup
For convenience, much of the code used in this hands-on lab is available as Visual Studio code snippets.
To check the prerequisites of the lab and install the code snippets:
1. Open a Windows Explorer window and browse to the lab’s Source\Setup folder.
2. Double-click the Dependencies.dep file in this folder to launch the Dependency Checker tool
and install any missing prerequisites and the Visual Studio code snippets.
3. If the User Account Control dialog is shown, confirm the action to proceed.
Page 4
Note: This process may require elevation. The .dep extension is associated with the Dependency
Checker tool during its installation. For additional information about the setup procedure and how to
install the Dependency Checker tool, refer to the Setup.docx document in the Assets folder of the
training kit.
Using the Code Snippets
Throughout the lab document, you will be instructed to insert code blocks. For your convenience, most
of that code is provided as Visual Studio Code Snippets, which you can use from within Visual Studio
2010 to avoid having to add it manually.
If you are not familiar with the Visual Studio Code Snippets, and want to learn how to use them, you can
refer to the Setup.docx document in the Assets folder of the training kit, which contains a section
describing how to use them.
Exercises
This hands-on Lab includes the following exercises:
1. Service Bus Management Operations
2. Service Bus Load Balancing
3. Durable Message Buffers
Estimated time to complete this lab: 45 minutes.
Note: When you first start Visual Studio, you must select one of the predefined settings collections.
Every predefined collection is designed to match a particular development style and determines
window layouts, editor behavior, IntelliSense code snippets, and dialog box options. The procedures in
this lab describe the actions necessary to accomplish a given task in Visual Studio when using the
General Development Settings collection. If you choose a different settings collection for your
development environment, there may be differences in these procedures that you need to take into
account.
Page 5
Getting Started: Creating a Service
Project
To complete the exercises in this lab, you require a Windows Azure AppFabric Project. Once you have
created a project, you can use it for all the AppFabric labs as well as your own projects.
Task 1 – Provisioning the Service Bus Namespace
In this task, you create a new project and create a service namespace to use the Windows Azure
AppFabric Service Bus.
1. Navigate to the Windows Azure AppFabric LABS portal and, if necessary, sign in using your
Windows Live ID credentials.
2. If this is the first time you access the AppFabric site, you need to create a new project.
Figure 1
AppFabric projects page
3. Enter a Project Name, such as your company name or your own name, and then click OK.
Figure 2
Creating a new Windows Azure AppFabric project
Page 6
4. In My Projects, click the newly created project to view its summary page.
Figure 3
Selecting a project to manage
5. Now, create a service namespace for this project. To add a service namespace, click the Project
Name link for your new project to open its summary page and then click Add Service
Namespace.
Figure 4
Windows Azure AppFabric project summary page
Note: A service namespace defines a boundary for each application exposed through the
Service Bus, allowing an application to uniquely address the AppFabric service endpoints.
6. Enter a name for your Service Namespace and then click Validate Name to ensure its
availability. Service names must be globally unique as they are hosted in the cloud and
accessible by whomever you decide to grant access. If the service is unavailable, you will need
to pick a different name. Once you have determined that the chosen namespace is valid and
available, click Create.
Page 7
Figure 5
Creating a new service namespace
7. Locate the new entry in the list of configured service namespaces and then wait for its Status
column to show the namespace as Active.
8. After the namespace is provisioned, click its Service Bus link to display the Service Bus Settings
page.
Figure 6
Project summary page listing available service namespaces
9. In the Service Bus Settings page, locate the Service Bus section and record the value shown for
the namespace section of the Service Gateway, the Default Issuer Name and Default Issuer
Key. You will need these values later on to configure access to the Service Bus.
Page 8
Figure 7
Service namespace Service Bus settings
Exercise 1: Service Bus Management
Operations
In this exercise, you will learn how to use the Windows Azure AppFabric Service Bus management
service to manage Connection Points. You will create a console application, leveraging the Service Bus
management service, which will enable you to create, enumerate, and delete Connection Points.
Figure 8
Service namespace Service Bus settings
Page 9
Task 1 – Adding Operations to Create, List and Delete Connection Points
In this task, you will create a console application and add the necessary code to enable the Service Bus
management operations that list, add or delete a connection point.
1. Open Microsoft Visual Studio 2010.
2. Open the ServiceBusManagementOperations.sln solution located in the Source\Ex1-
ManagementOperations\Begin\CS folder of this lab.
3. Add a reference to the Microsoft.ServiceBus.Channels assembly.
Note: If you cannot find the Microsoft.ServiceBus.Channels assembly in the .NET tab, use the
Browse tab to locate this assembly inside the %ProgramFiles%\Windows Azure AppFabric
SDK\V2.0\Assemblies\ folder.
4. Open the Program.cs file.
5. Add the following using statements at the top of the file.
(Code Snippet – IntroServiceBusFutures - Ex01 Using Statements - CS)
C#
using System.ServiceModel.Syndication;
using System.Xml;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Samples;
6. Add the highlighted code, from the following fragment, to the Main method. This code will
create the URI used by all connection points management operations, based on the service
namespace specified in the configuration.
(Code Snippet – IntroServiceBusFutures - Ex01 CreateManagementGatewayURI - CS)
C#
static void Main(string[] args)
{
// read account info from config
serviceNamespace = ConfigurationManager.AppSettings["ServiceNamespace"];
issuerName = ConfigurationManager.AppSettings["IssuerName"];
issuerSecret = ConfigurationManager.AppSettings["IssuerSecret"];
// Create the URI of the Connection Points Management Gateway
string connectionPointsManagementGateway = string.Format("https://{0}-
mgmt.{1}/Resources/ConnectionPoints", serviceNamespace,
ServiceBusEnvironment.DefaultServiceHostName);
managementUri = new Uri(connectionPointsManagementGateway);
Page 10
...
}
7. Replace the body of the DeleteConnectionPoint with the code highlighted in the following
snippet. This code first creates the runtime service bus URI where the connection point is
located. Afterwards, the runtime service bus URI and the account credential information is used
to invoke the DeleteConnectionPoint method, which effectively deletes the connection point.
(Code Snippet – IntroServiceBusFutures - Ex01 DeleteConnectionPoint - CS)
C#
private static void DeleteConnectionPoint(string
connectionPointsManagementGateway, string connectionPointName)
{
// create the service URI based on the service namespace
Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespace, connectionPointName);
Console.WriteLine("Attempting to delete a Connection Point at {0} ...",
runtimeUri);
// delete the connection point
ConnectionPointOperations.DeleteConnectionPoint(connectionPointName,
runtimeUri, managementUri, serviceNamespace, issuerName, issuerSecret);
}
8. Use the following highlighted code in the ListConnectionPoints method to display all the
existing connection points.
(Code Snippet – IntroServiceBusFutures - Ex01 ListConnectionPoints - CS)
C#
private static void ListConnectionPoints()
{
// create web request
WebClient webClient = new WebClient();
webClient.BaseAddress = managementUri.AbsoluteUri;
ACSTokenHelper.AddTokenHeaderToWebClient(webClient, serviceNamespace,
issuerName, issuerSecret);
string response = webClient.DownloadString(managementUri);
SyndicationFeed feed = SyndicationFeed.Load(XmlReader.Create(new
StringReader(response)));
// Print feeds
foreach (SyndicationItem item in feed.Items)
{
Page 11
ConnectionPoint connectionPoint =
((XmlSyndicationContent)item.Content).ReadContent<ConnectionPoint>();
Console.WriteLine("Id = {0}\r\nTitle = {1}\r\nMax Listeners =
{2}\r\nChannel Shape = {3}\r\n", item.Id, item.Title.Text,
connectionPoint.MaxListeners, connectionPoint.ChannelShape);
}
}
9. Update the CreateConnectionPoint method with the following code.
(Code Snippet – IntroServiceBusFutures - Ex01 CreateConnectionPoint - CS)
C#
private static void CreateConnectionPoint(string connectionPointName, string
maxListeners)
{
// Create the Service Endpoint URI based on the service namespace
Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespace, connectionPointName);
Console.WriteLine("Attempting to create a Connection Point for {0}
...", runtimeUri);
// Create the connection point
ConnectionPoint connectionPoint = new
ConnectionPoint(int.Parse(maxListeners), ChannelShape.Duplex);
ConnectionPointOperations.CreateConnectionPoint(connectionPointName,
runtimeUri, managementUri, serviceNamespace, issuerName, issuerSecret,
connectionPoint);
}
10. In Visual Studio, save all files.
Task 2 – Setting Account Information
1. Open the app.config file.
2. In the appSettings section, locate the ServiceNamespace setting and replace [YOUR-SERVICE-
NAMESPACE-DOMAIN] with the domain service namespace that you registered at the portal.
3. Next, locate the IssuerName and IssuerSecret settings and replace [YOUR-ISSUER-NAME] and
[YOUR-ISSUER-KEY] with the Default Issuer Name and Default Issuer Key for the service
namespace; these are the name and key generated for the service namespace at the portal
Web Site that you recorded during the Getting Started section. The figure below shows a
sample app.config file after replacing the value of these settings.
Page 12
Figure 9
App.config file after replacing the keys with your information
4. In Visual Studio, save all files.
Verification
In order to verify that you have performed every step in the exercise correctly, proceed as follows:
1. Press F5 to run the application. The console window appears and displays the different
management options.
Figure 10
Management options
2. Type 1 and press ENTER to create a new connection point.
Page 13
3. Name the connection point TestConnectionPoint and set the maximum number of listeners to
5. The program output is shown in the following figure.
Note: The Maximum Number of Listeners defines how many services can listen on a
particular endpoint.
Figure 11
Output when creating a new connection point
4. Type 2 and press ENTER to list all connection points. As shown in the following figure, the
previously created connection point should be listed.
Figure 12
Page 14
Connection Points listing
5. Type 3 and press ENTER to delete a connection point.
6. Type TestConnectionPoint and press ENTER to delete the previously created connection point.
Figure 13
Deleting the TestConnectionPoint
7. Type 2 and press ENTER to list all connection points. Verify that no connection points are now
listed, as shown in the following figure.
Figure 14
Page 15
No connection points are listed
8. Close the console application.
Exercise 2: Service Bus Load Balancing
This exercise shows the usage of the Anycast feature to communicate between clients and different
instances of an inventory service. This feature allows a service provider to programmatically subscribe a
number of listeners to a Service Bus connection point and when a message is sent to that connection
point, the Service Bus will randomly choose one listener to deliver this message. This allows the
developer to balance the load normally handled by a single instance of a listener among several
instances of that listener and provide a lightweight failover feature.
Task 1 – Creating the Service
In this task, you will create a service that implements a simple inventory service contract that contains
methods for listing items in stock, as well as creating and selling items. The service creates a connection
point for the InventoryService and then hosts the service itself.
1. Open Microsoft Visual Studio 2010.
2. Open the LoadBalancing.sln solution located in the Source\Ex2-LoadBalancing\Begin\CS folder
of this lab.
3. In the Service project, add a reference to the Microsoft.ServiceBus.Channels assembly.
Note: If you cannot find the Microsoft.ServiceBus.Channels assembly in the .NET tab, use the
Browse tab to locate this assembly in the %ProgramFiles%\Windows Azure AppFabric
SDK\V2.0\Assemblies\ folder.
4. In the Service project, open the Program.cs file.
5. Add the following highlighted namespace directives at the top of the file.
(Code Snippet – IntroServiceBusFutures - Ex02 ServiceUsingStatements - CS)
C#
using System;
using System.Configuration;
using System.IO;
Page 16
using System.Net;
using System.ServiceModel;
…
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Channels;
6. In the Main method, add the following highlighted code to create management and service
endpoint URIs for the Connection Point.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateManagementGatewayURI - CS)
C#
static void Main(string[] args)
{
Console.Title = "Service " + ServiceId;
// handle console closeing to close service connection
ConsoleCloseHandler.CloseHandler = CloseServiceConnection;
// read account info from config
serviceNamespace = ConfigurationManager.AppSettings["ServiceNamespace"];
issuerName = ConfigurationManager.AppSettings["IssuerName"];
issuerSecret = ConfigurationManager.AppSettings["IssuerSecret"];
try
{
// Create the URI of the Connection Points Management Gateway
string connectionPointsManagementGateway = string.Format("https://{0}-
mgmt.{1}/Resources/ConnectionPoints", serviceNamespace,
ServiceBusEnvironment.DefaultServiceHostName);
Uri managementUri = new Uri(connectionPointsManagementGateway);
// Create the URI of the Service Endpoint Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "InventoryService");
...
7. Use the following highlighted code to call the RetrieveConnectionPoint method, which uses the
management operations discussed in the previous exercise to retrieve the InventoryService
connection point (and creates it in case it does not exist).
(Code Snippet – IntroServiceBusFutures - Ex02 RetrieveConnectionPoint - CS)
C#
Page 17
// Create the URI of the Service Endpoint
Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespace, "InventoryService");
// Determine whether or not a Connection Point exists for this Service
Endpoint and create it if neccesary
RetrieveConnectionPoint(managementUri, runtimeUri);
8. Use the following highlighted code to create WCF custom client binding based on the
TcpServiceBusTransportBindingElement, which will enable the Service Bus' Anycast feature.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateBinding - CS)
C#
// Determine whether or not a Connection Point exists for this Service
Endpoint and create it if neccesary
RetrieveConnectionPoint(managementUri, runtimeUri);
// Start the Service
// Create custom binding based on the TcpServiceBusTransportBindingElement
var binding = new TcpServiceBusTransportBindingElement();
CustomBinding sdkClientBinding = new CustomBinding(binding);
9. Use the following highlighted code to create the endpoint’s Service Bus credentials, based on
the issuer name and secret key specified by the configuration.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateServiceBusCredentials - CS)
C#
// Create custom binding based on the TcpServiceBusTransportBindingElement
var binding = new TcpServiceBusTransportBindingElement();
CustomBinding sdkClientBinding = new CustomBinding(binding);
sdkClientBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
// Create the credentials object for the endpoint ServiceBusCredential serviceBusCredentialBehavior = new SharedSecretCredential(issuerName, issuerSecret);
10. Use the following highlighted code to create the host for the service, setting the endpoints and
service bus credentials.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateServceHost - CS)
C#
// Create the credentials object for the endpoint
ServiceBusCredential serviceBusCredentialBehavior = new
SharedSecretCredential(issuerName, issuerSecret);
Page 18
// Create the service host reading the configuration
host = new ServiceHost(typeof(InventoryService), runtimeUri);
// Add the Service Bus credentials to all endpoints specified in configuration
ServiceEndpoint serviceEndPoint =
host.AddServiceEndpoint(typeof(IInventoryContract), sdkClientBinding,
runtimeUri);
serviceEndPoint.Behaviors.Add(serviceBusCredentialBehavior);
11. Use the following highlighted code to start the service, opening the host connection.
(Code Snippet – IntroServiceBusFutures - Ex02 OpenHostConnection - CS)
C#
// Add the Service Bus credentials to all endpoints specified in configuration
ServiceEndpoint serviceEndPoint =
host.AddServiceEndpoint(typeof(IInventoryContract), sdkClientBinding,
runtimeUri);
serviceEndPoint.Behaviors.Add(serviceBusCredentialBehavior);
// Open the service
Console.WriteLine("Starting service at {0} ...", serviceEndPoint.Address);
host.Open();
Console.WriteLine("Service hosted at: {0}", serviceEndPoint.Address);
12. Save and close the Program.cs file.
Task 2 – Creating the Client
1. In the Client project, add a reference to the Microsoft.ServiceBus.Channels assembly.
Note: If you cannot find the Microsoft.ServiceBus.Channels assembly in the .NET tab, use the
Browse tab to locate this assembly inside the %ProgramFiles%\Windows Azure AppFabric
SDK\V2.0\Assemblies\ folder.
2. In the Client project, open the Program.cs file.
3. Add the following highlighted namespace directives at the top of the file.
(Code Snippet – IntroServiceBusFutures - Ex02 ClientUsingStatements - CS)
C#
using System;
Page 19
using System.Configuration;
using System.IO;
using System.Net;
using System.ServiceModel;
using System.Collections;
using System.Collections.Generic;
using System.ServiceModel.Channels;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Channels;
4. In the Main method, use the following highlighted code to create the service URI.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateClientServiceURI - CS)
C#
static void Main(string[] args)
{
Console.Title = "Client " + ServiceId;
// handle console closeing to close service connection
ConsoleCloseHandler.CloseHandler = CloseServiceConnection;
// read account info from config
serviceNamespace = ConfigurationManager.AppSettings["ServiceNamespace"];
issuerName = ConfigurationManager.AppSettings["IssuerName"];
issuerSecret = ConfigurationManager.AppSettings["IssuerSecret"];
try
{
// create the service URI based on the service namespace
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespace, "InventoryService");
5. Use the following highlighted code to create the binding used by the client to connect to the
service bus connection point.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateClientBinding - CS)
C#
// create the service URI based on the service namespace
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespace, "InventoryService");
// create custom binding based on the TcpServiceBusTransportBindingElement
var loadBalancingBinding = new TcpServiceBusTransportBindingElement(); CustomBinding sdkClientBinding = new CustomBinding(loadBalancingBinding);
Page 20
6. Use the following highlighted code to create the service channel factory.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateClientChannelFactory - CS)
C#
// create custom binding based on the TcpServiceBusTransportBindingElement
var loadBalancingBinding = new TcpServiceBusTransportBindingElement();
CustomBinding sdkClientBinding = new CustomBinding(loadBalancingBinding);
// create the channel factory loading the configuration
channelFactory = new ChannelFactory<IInventoryChannel>(sdkClientBinding, new
EndpointAddress(serviceUri));
7. Use the following code to create the service bus credentials and add them to the endpoint.
(Code Snippet – IntroServiceBusFutures - Ex02 AddCredentials - CS)
C#
// create the channel factory loading the configuration
channelFactory = new ChannelFactory<IInventoryChannel>(sdkClientBinding, new
EndpointAddress(serviceUri));
// apply the Service Bus credentials
ServiceBusCredential serviceBusCredentialBehavior = new
SharedSecretCredential(issuerName, issuerSecret);
channelFactory.Endpoint.Behaviors.Add(serviceBusCredentialBehavior);
8. Use the following highlighted code to open the inventory service connection.
(Code Snippet – IntroServiceBusFutures - Ex02 OpenServiceChannel - CS)
C#
// apply the Service Bus credentials
ServiceBusCredential serviceBusCredentialBehavior = new
SharedSecretCredential(issuerName, issuerSecret);
channelFactory.Endpoint.Behaviors.Add(serviceBusCredentialBehavior);
// create and open the client channel to connect to the InventoryService
Console.WriteLine("Creating connetion to {0} ...", serviceUri);
inventoryChannel = channelFactory.CreateChannel(); inventoryChannel.Open();
9. In the CreateItem method, use the following highlighted code to create an item. This method
prompts users for the new item’s information and invokes the CreateItem method on the
service.
(Code Snippet – IntroServiceBusFutures - Ex02 CreateItemMethod - CS)
Page 21
C#
private static void CreateItem(IInventoryChannel inventoryChannel)
{
// Prompt user for item's data
Console.Write("Enter new item's Title:");
string title = Console.ReadLine();
Console.Write("Enter new item's Quantity:");
int quantity = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter new item's Description:");
string description = Console.ReadLine();
// call service to create an item
var soldItem = inventoryChannel.CreateItem(title, quantity, description);
Console.WriteLine("Item {0} created", soldItem.InventoryItemId);
Console.WriteLine("Title = {1}, Quantity = {2}", soldItem.InventoryItemId,
soldItem.Title, soldItem.Quantity);
}
10. In the ListInventory method, use the following code to retrieve all items in stock using the
service and list them in the console window.
(Code Snippet – IntroServiceBusFutures - Ex02 ListInventoryMethod - CS)
C#
private static void ListInventory(IInventoryChannel inventoryChannel)
{
// call service to list items
IEnumerable<InventoryItem> inventoryList =
inventoryChannel.GetInventory();
Console.WriteLine("Current Items in Stock:");
foreach (InventoryItem item in inventoryList)
{
Console.WriteLine("ItemId = {0}, Title = {1}, Quantity = {2}",
item.InventoryItemId, item.Title, item.Quantity);
}
}
11. In the SellItem method, use the following highlighted code to sell an item using the service and
the information provided by the user.
(Code Snippet – IntroServiceBusFutures - Ex02 SellItemMethod - CS)
C#
private static void SellItem(IInventoryChannel inventoryChannel)
{
Page 22
// Prompt user for item's data
Console.Write("Enter ItemId of item to be sold:");
int itemId = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Quantity of item to be sold:");
int quantity = Convert.ToInt32(Console.ReadLine());
// call service to update item
var soldItem = inventoryChannel.SellItem(itemId, quantity);
Console.WriteLine("Item updated!");
Console.WriteLine("ItemId = {0}, Title = {1}, Quantity = {2}",
soldItem.InventoryItemId, soldItem.Title, soldItem.Quantity);
}
12. In Visual Studio, save all files and build the solution.
Task 3 – Setting Account Information
1. Open the app.config file.
2. In the appSettings section, locate the ServiceNamespace setting and replace [YOUR-SERVICE-
NAMESPACE-DOMAIN] with the domain service namespace that you registered at the portal.
3. Locate the IssuerName and IssuerSecret settings and replace [YOUR-ISSUER-NAME] and
[YOUR-ISSUER-KEY] with the Default Issuer Name and Default Issuer Key for the service
namespace; these are the name and key generated for the service namespace at the portal
Web Site that you recorded during the Getting Started section. The figure below shows a
sample app.config file after replacing the value of these settings.
Figure 15
App.config file after replacing the keys with your information
4. In Visual Studio, save all files.
Page 23
Verification
In order to verify that you have performed every step in the exercise correctly, proceed as follows:
Note: If you ran this exercise previously, make sure that the InventoryService endpoint does
not exist. If it does, you can use the solution in Exercise 1 to delete it.
1. To delete the InventoryService endpoint, if it already exists, perform the following steps;
otherwise, you may skip to step 8 in this verification.
2. In another instance of Visual Studio, open the ServiceBusManagementOperationsEnd.sln
solution (from the first exercise of this lab) located at Source\Ex1-
ManagementOperations\End\CS.
3. In the App.config file, replace the [YOUR-SERVICE-NAMESPACE-DOMAIN], [YOUR-ISSUER-
NAME], and [YOUR-ISSUER-KEY] placeholders with the Service Namespace, Default Issuer
Name, and Default Issuer Key that you have done during the provisioning process.
4. Press F5 to run the application.
5. Type 3 and press ENTER to delete a connection point.
6. Type InventoryService for the name of the connection point to delete and press ENTER. The
outcome is shown in the following figure.
Figure 16
Deleting the InventoryService
Note: The reason why the InventoryService connection point is deleted is to avoid exceeding
the maximum amount of services that can be connected to that connection point.
Page 24
7. Type 4 and press ENTER to close the console.
8. In the Visual Studio instance that has the LoadBalancing solution open, set the Service project
as the startup project.
9. Press CTRL + F5 to start a new instance of the Service project.
Figure 17
First Service Instance
10. Launch a second instance of the Service project. To do this, in Visual Studio press CTRL + F5. You
will use two instances of the service to verify the load balancing feature of the Service Bus. Note
that each console window has a different service GUID.
Page 25
Figure 18
Two different service instances running
11. Set the Client project as the startup project.
Important: The Service Bus closes connections from clients after an entire minute without
receiving requests from them. If you receive an error, close the client instance and open a new
one.
12. Press CTRL + F5 to start a new instance of the Client project.
Page 26
Figure 19
Client instance running
13. In the Client console, type 1 and press ENTER five times, to list items in stock five times. Notice
how all the requests are handled by the same service instance.
Figure 20
Page 27
Requests being handled by the same service instance.
Note: All requests from the same client are handled by the same service instance by design.
This is because load balancing maintains the session, so once the channel is open, it will
continue to work with the same service instance.
14. Press CTRL + F5 to start another instance of the Client project.
15. In the Client console, type 1 and press ENTER six times, to list items in stock six times. Notice
how all requests are handled by the other service instance.
Figure 21
The requests performed by the new client are handled by a different service
Important: Load balancing does not ensure that when opening two clients, their requests will
be handled by different services. If all eleven requests were handled by the same service,
simply launch another client and perform requests with it until the other service handles them.
16. Close all console applications.
Page 28
Exercise 3: Durable Message Buffers
Message Buffers enable asynchronous message processing by providing small, temporary cache
locations where messages are pushed and stored for short periods until they can be retrieved.
Applications can access Message Buffers using simple HTTP requests, without the need for any specific
support from the Windows Azure AppFabric SDK, thus allowing clients in other platforms equal access to
this feature.
In this exercise, you will learn how to use Message Buffers to achieve basic asynchronous messaging
functionality in a consistent and fault-tolerant way. Additionally, you will see that messages stored in
the buffer are persisted and examine the peek-lock and delete pattern and how to use it to provide
guarantees that a message is delivered at least once, even in the face of client failure.
Task 1 – Implementing Basic Operations with Message Buffers
In this task, you will update a simple console application to enable it to create a message buffer and use
it to store, retrieve, lock, and delete messages in the buffer.
1. Open Microsoft Visual Studio 2010.
2. Open the DurableMessageBuffer.sln solution located in the Source\Ex3-
DurableMessageBuffer\Begin\CS folder of this lab.
3. Open the Program.cs file.
4. Add the highlighted code in the following fragment to method Main. This code retrieves the
Access Control service (ACS) authorization tokens required to manage and access the message
buffer.
(Code Snippet – IntroServiceBusFutures - Ex03 Retrieve ACS token - CS)
C#
static void Main(string[] args)
{
...
try
{
Console.WriteLine("Attempting to gather ACS tokens...");
// Get an ACS token to use for management operations; these tokens are
cached in the client and only retrieved once
string managementAddressRoot = string.Format(CultureInfo.InvariantCulture,
"{0}-mgmt.{1}", serviceNamespace, RestMessageBufferClient.HostName);
string runtimeAddressRoot = string.Format(CultureInfo.InvariantCulture,
"{0}.{1}", serviceNamespace, RestMessageBufferClient.HostName);
Page 29
string managementToken =
RestMessageBufferClient.GetTokenFromACS(serviceNamespace, "http://" +
managementAddressRoot, managementUsername, managementPassword);
string runtimeToken =
RestMessageBufferClient.GetTokenFromACS(serviceNamespace, "http://" +
runtimeAddressRoot, runtimeUsername, runtimePassword);
Console.WriteLine("Successfully acquired ACS tokens.");
// Retrieve Message Buffer
messageBufferClient = RetrieveMessageBuffer(serviceNamespace, bufferName,
managementToken, runtimeToken);
...
}
Note: The Windows AppFabric Access Control service (ACS) secures access to a message
buffer. Each request to the message buffer service must include an authorization header that
contains a token issued by ACS.
The code shown above retrieves two tokens. The first token authorizes actions against the
management service and is used during the creation of the message buffer. The second token
provides authentication and authorization for operations issued against the message buffer
itself, and used for reading, locking, and deleting messages.
5. Locate the RetrieveMessageBuffer method and replace its body with the code highlighted in
the following snippet. This code retrieves an object that you can then use to interact with a
message buffer.
(Code Snippet – IntroServiceBusFutures - Ex03 RetrieveMessageBuffer method - CS)
C#
private static RestMessageBufferClient RetrieveMessageBuffer(string
serviceNamespace, string bufferName, string managementToken, string
runtimeToken)
{
RestMessageBufferClient messageBufferClient;
try
{
Console.WriteLine("Attempting to create buffer named " + bufferName +
"...");
// Retrieve message Buffer
messageBufferClient =
RestMessageBufferClient.GetMessageBuffer(managementToken, runtimeToken,
serviceNamespace, bufferName, MessageVersion.Soap12WSAddressing10);
Page 30
Console.WriteLine("Buffer found.");
}
catch (EndpointNotFoundException)
{
Console.WriteLine("Buffer doesn't exist. Creating...");
// Create new message buffer
messageBufferClient =
RestMessageBufferClient.CreateMessageBuffer(managementToken, runtimeToken,
serviceNamespace, bufferName, bufferName, new MessageBufferDescription(),
MessageVersion.Soap12WSAddressing10);
Console.WriteLine("Buffer " + bufferName + " created successfully.\n");
}
return messageBufferClient;
}
Note: The code shown above retrieves an instance of the RestMessageBufferClient class. This
helper class, originally supplied in the Windows Azure AppFabric SDK, wraps the REST API
required to create and use a message buffer.
6. Now, add code to enqueue a message into a message buffer. To do this, locate the
SendMessageToBuffer method and replace its body with the following (highlighted) code.
(Code Snippet – IntroServiceBusFutures - Ex03 SendMessageToBuffer method - CS)
C#
private static void SendMessageToBuffer(RestMessageBufferClient
messageBufferClient)
{
// Prompt used for message to be sent
Console.Write("Enter message text to send, followed by ENTER: ");
string messageText = Console.ReadLine();
// Send message
messageBufferClient.Send(Message.CreateMessage(MessageVersion.Default,
"test", messageText));
Console.WriteLine("Message sent successfully.\n");
}
7. Next, replace the body of the PeekLockMessage method with the following (highlighted) code.
This method atomically retrieves and locks a message for processing.
(Code Snippet – IntroServiceBusFutures - Ex03 PeekLockMessage method - CS)
Page 31
C#
private static Message PeekLockMessage(RestMessageBufferClient
messageBufferClient)
{
// Peek-lock message
Message message = null;
try
{
message = messageBufferClient.PeekLock(PeekLockTime);
string content = message.GetBody<string>();
Console.WriteLine("Received message with body: \n" + content + "\n");
}
catch (TimeoutException e)
{
Console.WriteLine("There are no messages in the Message Buffer.");
}
return message;
}
Note: An application can retrieve a message and delete it from a message buffer in a single
atomic operation. Note, however, that if the application can crash before it can completely
process a message, there is no guarantee that the message will be processed successfully at
least once. To provide such assurances, message buffers support peek/lock operations that
allow an application to retrieve and then place a lock on a message. While a message is locked,
it is guaranteed not to be delivered to other receivers. Once the application finishes processing
a message, it removes it from the buffer. If the application is unable to complete its processing
before the lock expires, for example, after it crashes, the message becomes available once
again and can be retrieved by other receivers. Note that this requires that processing be
idempotent. In other words, processing the message multiple times, even if only partially
completed, always produces the same result allowing the final state to remain consistent.
8. To complete processing on a locked message and delete it from the buffer, implement the
DeleteLockedMessageFromBuffer method, as shown below.
(Code Snippet – IntroServiceBusFutures - Ex03 DeleteLockedMessageFromBuffer method - CS)
C#
private static void DeleteLockedMessageFromBuffer(RestMessageBufferClient
messageBufferClient, Message message)
{
// Delete message
messageBufferClient.DeleteLockedMessage(message);
Page 32
Console.WriteLine("Message deleted successfully.\n");
}
Note: An application can use this method to delete a previously locked message once it has
successfully dealt with it, thus ensuring that the message is processed at least once. If a locked
message fails to be deleted in time, once the lock expires, the message will become available
again for processing.
9. Locate the UnlockMessage method and replace its body with the following (highlighted) code
that unlocks a message without deleting it from the message buffer.
(Code Snippet – IntroServiceBusFutures - Ex03 UnlockMessage method - CS)
C#
private static void UnlockMessage(RestMessageBufferClient messageBufferClient,
Message message)
{
// Release message lock
messageBufferClient.ReleaseLock(message);
Console.WriteLine("Message lock released. Message was kept in the
buffer.\n");
}
Note: Unlocking a message without deleting it allows the message to be retrieved again by
other receivers.
10. Finally, insert the following (highlighted) code into the body of the DeleteMessageBuffer
method.
(Code Snippet – IntroServiceBusFutures - Ex03 DeleteMessageBuffer method - CS)
C#
private static void DeleteMessageBuffer(RestMessageBufferClient
messageBufferClient)
{
// Delete message buffer
messageBufferClient.DeleteMessageBuffer();
Console.WriteLine("Message buffer deleted successfully.");
}
Page 33
Note: Applications can use this method to delete an existing message buffer and remove all
associated state including any messages currently in the buffer.
Task 2 – Setting Account Information
1. Open the app.config file.
2. In the appSettings section, locate the ServiceNamespace setting and replace [YOUR-SERVICE-
NAMESPACE-DOMAIN] with the domain service namespace that you registered at the portal.
3. Next, locate the IssuerName and IssuerSecret settings and replace [YOUR-ISSUER-NAME] and
[YOUR-ISSUER-KEY] with the Default Issuer Name and Default Issuer Key for the service
namespace; these are the name and key generated for the service namespace at the portal
Web Site that you recorded during the Getting Started section. The figure below shows a
sample app.config file after replacing the value of these settings.
Figure 22
App.config file after replacing the keys with your information
4. In Visual Studio, save all files.
Verification
In order to verify that you have performed every step in the exercise correctly, proceed as follows:
1. Press CTRL + F5 to run the console application.
Note: These are CTP bits, so while running this verification you might receive an exception
message; you can safely ignore it and perform the step again.
2. Enter the name of the buffer to use and then press ENTER. For this verification, you can use
SampleBuffer. A new message buffer with the specified name will be created or, if it already
exists, it will be retrieved. Notice that the console shows a menu with every operation available.
Page 34
Figure 23
Creating a message buffer
3. Press 1 to send a message to the buffer. Then, enter the message you want to send and press
ENTER. For this verification, you can use Sample Message 1.
4. Repeat the previous step an additional two times using different messages (for example,
Sample Message 2 and Sample Message 3).
Page 35
Figure 24
Sending messages to the buffer
5. In Visual Studio, press CTRL + F5 to run a second instance of the console client.
6. Enter the name of the buffer you specified in step 2 and press ENTER. When the client attempts
to create the buffer, it will find an existing instance with that name—created by the first client—
and use that instead. A menu with available operations will be shown.
Page 36
Figure 25
Retrieving an existing message buffer
7. Press 2 to retrieve (peek and lock) a message from the buffer. Verify that the first message you
sent in step 3 is retrieved.
8. Press D to delete the message from the buffer.
Figure 26
Page 37
Retrieving a message and deleting it
9. In the console window for the client launched during step 1, press 4 to exit the application.
Note: This allows you to verify that messages can still be retrieved even after the client that
sent them is no longer running.
10. In the remaining client, press 2 to retrieve a message from the buffer. Verify that you retrieve
the second message you sent to the buffer.
11. Press D to delete that message from the buffer.
Figure 27
Retrieving a message and deleting it
12. Press 2 to retrieve another message. Verify that the third message you sent to the buffer is
retrieved.
13. Press any key other than D to unlock the message. This keeps the message that you just
retrieved in the buffer.
Page 38
Figure 28
Retrieving message and releasing its lock
14. Once again, press 2 to choose to retrieve a message. Verify that you recover the same message
that you retrieved in step 12.
Figure 29
Retrieving the previous message one more time
15. Press D to delete the message from the buffer.
16. Press 2 to retrieve a message. Verify there are no more messages stored in the message buffer.
Page 39
Figure 30
Message buffer showing no messages
17. Press 3 to choose the delete message buffer operation.
Figure 31
Deleting a message buffer
18. Press ENTER to exit the console application.
Page 40
Summary
In this hands-on lab, you learned how to manage Connection Points. These management tasks enable
you to create, enumerate and delete Connection Points on the Windows Azure AppFabric Service Bus.
You also learned how to use the Anycast (load balancing) feature, by subscribing various listeners
(services) to a Service Bus connection point, letting the Service Bus randomly choose one listener to
deliver the message. Finally, you saw how messages pushed to a durable message buffer can be
retrieved at a later time to enable asynchronous message processing.