Monday, September 24, 2012

BizTalk 2010 R2 CTP: Azure Service Bus Integration–Part 3 Sending message to Service Bus Queue

This is the third post  in a series where I discuss integrating BizTalk 2010 R2 CTP with the Azure Service Bus.  In Part 1 I discussed BizTalk receiving a message from a Service Bus Queue.  In Part 2 I expanded on the scenario that I described in Part 1 but added support for Brokered Messaging Properties.  In this post I am going to switch gears and have BizTalk send messages to a Service Bus Queue.

Scenario
In my previous posts, I have focused on Power Outage scenarios as this is an industry that I am very familiar with.  In Post 2, I discussed situations where we may have critical customers and we want Power Outage incident tickets, when critical customers are involved, to have a higher priority. Whenever you are dealing with Critical Customers you generally have dire circumstances for getting their power restored as quickly as possible.  Whether you are dealing with Hospital,s where people could die, or Oil and Gas operations where being down may result in revenue losses in the hundreds of thousands of dollars per hour (or more).  Often times, Power Delivery organizations will have Major Account Representatives (or MAR for short).  These people are responsible for maintaining business relationships with these types of customers to ensure service levels and expectations are being met.

In Part 2, we left off delivering messages to a Work Order Management system that can dispatch these trouble events to field operations staff to address.  We created two separate paths: one for regular customers and one for critical customers.  The intention of this post is to have the Work Order Management system provide a message back to BizTalk that BizTalk can push to an “Estimated Time of Restore” queue.  A MAR account application can then subscribe to these events.  Having this information at the MAR’s fingertips will allow them to contact the customer to give them the bad, or good, news.

Service Bus Client
  • A new C# console application has been added to our solution from the previous posts called BrokeredMessageFromBizTalk.
image
  • Next we are going to add a class called EstimatedTimeToRestore.  It looks an awful lot like our PowerOut class from our previous scenario with the major difference being the RestoreTime property.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BrokeredMessageFromBizTalk
{
    public class EstimatedTimeToRestore
    {
        public string CustomerName;
        public string PhoneNumber;
        public string Address;
        public DateTime RestoreTime;
    }
}
  • Below is the code that I have placed in Program.cs. I do have a section of code commented out that will allow us to write out an instance of EstimatedTimeToRestore to disk. We will want a copy of this file so that we can use it within BizTalk to generate an XSD schema.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.Serialization;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;

namespace BrokeredMessageFromBizTalk
{
    class Receiver
    {
        const string QueueName = "<queue_name>";
        static string ServiceNamespace = "<your_namespace>";
        static string IssuerName = "owner";
        static string IssuerKey = "<your_key>";

        static void Main(string[] args)
        {

            //Uncomment this code if you want to write an instance of your data class to disk
            //EstimatedTimeToRestore etr = new EstimatedTimeToRestore();
            //etr.Address = "1 Calgary Way";
            //etr.CustomerName = "General Hospital";
            //etr.PhoneNumber = "403-1234567";
            //etr.RestoreTime = DateTime.Now;
            //using (FileStream writer = new FileStream("c:/temp/ETRfile.xml",FileMode.Create, FileAccess.Write))
            //{
            //    DataContractSerializer ser = new DataContractSerializer(typeof(EstimatedTimeToRestore));
            //    ser.WriteObject(writer, etr);
            //}
          
         //Create instance of tokenProvider using our credentials
            TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
                Receiver.IssuerName, Receiver.IssuerKey);
            Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", Receiver.ServiceNamespace, string.Empty);
            MessagingFactory messagingFactory = MessagingFactory.Create(uri, tokenProvider);
            QueueClient qc =  messagingFactory.CreateQueueClient(Receiver.QueueName, ReceiveMode.ReceiveAndDelete);
            BrokeredMessage bm;
            while ((bm = qc.Receive(new TimeSpan(hours: 0, minutes: 0, seconds: 5))) != null)
            {
                var data = bm.GetBody<EstimatedTimeToRestore>(new DataContractSerializer(typeof(EstimatedTimeToRestore)));
                Console.WriteLine(String.Format("An estimated time of restore {0} has been received for {1}", data.RestoreTime, data.CustomerName));
            }
        }
    }
}
  • Most of this code is nothing that you haven’t seen before as part of SDKs or other Blog posts out there.  The one line that you do need to be aware where we serialize the message that was pulled off of the Queue into an instance of our EstimatedTimeOfResponse class.  This allows us to use a typed response.  You may recall from Post 1 and 2 that we were using this same Serializer when pushing messages to the Queue so that BizTalk will be able to receive typed messages from the Queue.  The process is no different on the receive side.
var data = bm.GetBody<EstimatedTimeToRestore>(new DataContractSerializer(typeof(EstimatedTimeToRestore)));

Creating PowerRestoreQueue
In our previous examples, we had the client application ensure that our Queue existed prior to putting a message in it.  This time around we are going to use the Azure Service Bus Portal to perform this operation.

As of this writing, all Service Bus configuration occurs within the “old” portal.  To add a queue, select your namespace and then click on the New Queue button.  You will then need to provide a name and configure optional properties, if so desired, and then click the OK button.  You will then see the queue has been added successfully.  For the purpose of this example we are going to use a name of powerrestore.

image

Modifying BizTalk Solution
  • Once again we are going to want to generate a typed XSD schema based upon the sample file that was generated by our Queue Client Code.    We can do so by:
    • Right mouse clicking on BizTalk project (PowerOutage) - Add - Add Generated Items.
    • When prompted, click on the Generate Schemas label and then click the Add button.
    • Select Well-Formed XML from the Document type dropdown and then we need to provide the name of our sample file.  Click OK to proceed.
  • We now need to re-deploy our BizTalk application by right mouse clicking on our Solution and clicking Deploy Solution.
  • Within the BizTalk Administration Console we need to now add a Receive Port and Receive location.  There isn’t anything super special about this Receive Location.  We will use the FILE Adapter, the XML Receive Pipeline and will use a local file system URI.  Do make a note of the Receive Port Name as we will use it as a filter in our Send Port that we are about to create.
image
  • Create a new Send Port using the new SB-Messaging Adapter and specify the PassThruTransmit Send pipeline.
image
  • Click the Configure button.  We now need to specify our Destination URL including our Namespace(underlined in green) and the name of our queue (underlined in red).
image
  • Next, click the Authentication tab and modify the Access Control STS URI. We need to provide our namespace (underlined in green).  Be sure to leave the –sb string after the namespace.
image

  • Lastly, we need to create a Filter so that when BizTalk receives a message from our Receive Port, that we previously configured, that we send it to the Azure Service Bus queue.  To do this we need to click on Filters and then select the BTS.ReceivePortName  property while specifying  our Receive Port Value Name.
image

Testing our Solution
In order to test our application, we will focus on the BizTalk aspects first. 
  • We will want to drop our sample XML file, that we previously generated from our Queue client, and drop it in our BizTalk receive location folder:
image
  • BizTalk will now pick up this file and deliver it to our Service Bus Queue.
  • Next, we can start up an instance of our Queue Client.  We will soon discover that our message has been dequeued and that our console application has been updated informing us that an updated Estimated time of restore has been provided for us.
image


Conclusion
Once again, a very seemless experience when taking your existing BizTalk skills and using them to create Cloud or Hybrid solutions.  The only real area that you need to be concerned with is the Serializing of messages that you are putting or pulling from the queue.

This series will continue, I have a few other areas that I plan on exploring related to Azure Service Bus and BizTalk integration. Stay tuned...


4 comments:

Howard S. Edidin said...

Nice series of articles. Getting a jump start on R2 is very helpfull

Kent Weare said...

Thanks Howard!

Saravana Kumar said...

Looks like you are on fire Kent, I'll just redirect anyone who ask me about BizTalk-Service Bus integration to your blog :-)

Kent Weare said...

Thanks Saravana...more coming stay tuned.