Wednesday, September 28, 2011

Expose BizTalk endpoints / orchestration via windows azure app fabric

With the release of biztalk 2010 and microsoft new cloud services there's a completely new way of exposing service endpoints.
It's done via windows azure app fabric service bus technology and you can get it up and running simply by creating an account

This is, in my opinion, a huge improvement as compared to how you had to proceed before in order to expose services to the outside world.
It involved a lot of infrastucture like setting up fw servers - load balancing not to mention fw rules to open up for external partner applications...

Because I've been struggling so much with all of the above mentioned issues, I was eager to test this new technology.

I started with a simple console application hosting a WCF service.
-> That's quite useless in a production environment as you don't have any / very limited monitoring capacity on a console window. So I moved on to test exposing a biztalk orchestration to the cloud.

1 - EXPOSE THE SERVICE

In order to do that you need:

* windows 7 or windows 2008 R2 as operating system.
(these are the only operating systems supporting service activation in IIS which is needed for cloud hosting scenarios)

* visual studio 2010, sql server 2008 R2 and biztalk 2010
* BizTalk server 2010 feature pack ( http://go.microsoft.com/fwlink/?LinkId=204701)
* Windows Azure appfabric SDK (http://go.microsoft.com/fwlink/?LinkId=204209)
* Windows Server AppFabric (http://www.microsoft.com/downloads/sv-se/details.aspx?displaylang=sv&FamilyID=467e5aa5-c25b-4c80-a6d2-9f8fb0f337d2)

In addition to the above components we need an azure account.
You can sign up for an account here:
(http://www.microsoft.com/windowsazure/features/virtualnetwork)


Create a new Service Bus instance following the guidelines in the picture below:



After we've installed the above components and created our Service Bus we're ready to start coding!

We'll create an extremely simple biztalk assembly consisting of an orchestration, input schema (MultRequest.xsd), ouput schema (MultResponse.xsd) and map (TransformToResp.btm)

The orchestration receives our MultRequest message, transform it to our MultResponse message using the multiplication functoid. Finally the message is sent back to the logical request / response port that has to be configured as PUBLIC!!

See pictures below:



Create a strong key file and deploy the assembly to biztalk runtime.
Now we need to expose our "Multiplication Service Orchestration" to the cloud. This is done thanks to the WCF publishing wizzard and the BizTalk server 2010 feature pack we just installed.

Start Biztalk WCF publishing wizzard -> click next on the welcome screen -> Choose service endpoint, check the boxes and choose the application where you want the generated receive port to be created, click next. -> Check "Add a service bus endpoint", click next -> Choose "Publish BizTalk orchestration...", click next -> Choose the previously deployed dll, click next -> leave all the boxes checked, click next -> leave default target namespace, click next -> Check "Allow anonymous access to WCF service", click next -> configure the service bus endpoint according to picture below: (leave default bindings, specify your service buss endpoint and check the boxes)


Enter the service bus credentials:


Click next -> review the settings and click create.
(There's a more friendly version of how to configure these settings here:
http://social.technet.microsoft.com/wiki/contents/articles/expose-biztalk-applications-on-the-cloud-using-appfabric-connect-for-services.aspx)

There're 4 more steps we need to do in order to push out our service on the cloud.

1 - Change the application pool for the application in IIS to the ASP.NET 4.0 default app pool.
(make sure the app pool is running under the same account as the biztalk isolated host!)

2 - Configure our application in IIS manager to autostart.
Right click the application -> choose manage WCF, WF services -> choose configure -> click autostart on the left hand side meny -> activate.

3 - Bind the orchestration that we previously deployed to the autogenerated receive port.

4 - Start the application.

If everything was ok your service should now be registered in your azure app service bus and discoverable.
You can check if service activation was successfull by browsing to:
"https://[your service bus namespace].servicebus.windows.net"
You should see your service listed and there should be a mex endpoint discribing how to invoke your service.

2 - CONSUME THE SERVICE


The easiest way to test / and consume our service is to create a console application and add a service reference to the service we just created.

Add a new console project to the solution that contains your biztalk project.
Right click the console project and choose add service reference.
Enter the address to the discovery end point, in my case:
"https://jtapps.servicebus.windows.net/"
(replace jtapps with your namespace)
Select the service we just created in the window below and click ok.
This will automatically add a library reference: "System.ServiceModel.dll"
and create a basic configuration file for consuming this service.

We need to add credentials to access the service endpoint.
This is done by adding the following xml structure inside the <system.serviceModel> node:


<behaviors>
        <endpointBehaviors>
          <behavior name="sharedSecretClientCredentials">
            <transportClientEndpointBehavior credentialType="SharedSecret">
              <clientCredentials>
                <sharedSecret issuerName="owner" issuerSecret="[your secret key]" />
              </clientCredentials>
            </transportClientEndpointBehavior>
          </behavior>
        </endpointBehaviors>
      </behaviors>


we also need to tell the "client enpoint configuration" to use this "behavior" (ie these credentials)
it's done under the <client> node by configuring the attribute "behaviorConfiguration" (see the text in bold below). Also note the attribute "bindingConfiguration" that is set to "RelayEndpoint" -> the service bus just forward our request, it doesn't host anything.


<client>
            <endpoint address="sb://jtapps.servicebus.windows.net/ExposeOrchInCloudTest/WcfService_ExposeOrchInCloudTest.svc"
                binding="netTcpRelayBinding" bindingConfiguration="RelayEndpoint"
                contract="ExposedOrchInCloud.WcfService_ExposeOrchInCloudTest"
                name="RelayEndpoint" behaviorConfiguration="sharedSecretClientCredentials" />


Below is a snapshot overview of the configuration file:


That's the configuration of our client, now we just need some lines of code that will call our service bus endpoint.

We define our client to use the RelayEndpoint address, we define a simple request message and we call the service display the result.

Below is the code sample with the main points highlightened in bold and finally a picture of a sample call to the service. The client console window shows the request parameters and the result we get back. In the background you can see the biztalk admin console with a tracking query that shows the message flow inside biztalk runtime.

So we make a request from our local dev computer or server -> it calls an exposed endpoint on the azure service bus that can be a server center in northern america / europe / asia ... anywhere -> it goes back to our server / dev computer, handling the request and sending the response back the same way.
It's slow! And for the moment I think this it's only to be used for asynchronous type of service calls.
But it's extremely loosely coupled and I think a very fast (and secure!) way to expose services to the outside world.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestExposedOrchClient
{
    class Program
    {
        static void Main(string[] args)
        {
            ExposedOrchInCloud.WcfService_ExposeOrchInCloudTestClient myTestClient = new ExposedOrchInCloud.WcfService_ExposeOrchInCloudTestClient("RelayEndpoint");
            ExposedOrchInCloud.MultRequest myTestRequest = new ExposedOrchInCloud.MultRequest();
            myTestRequest.value1 = new decimal(2.5);
            myTestRequest.value2 = new decimal(3.0);
            try
            {
                Console.WriteLine("Calling biztalk cloud service to multiply:");
                Console.WriteLine("value1: " + System.Convert.ToString(myTestRequest.value1) + " with");
                Console.WriteLine("value2: " + System.Convert.ToString(myTestRequest.value2));
                ExposedOrchInCloud.MultResponse myResult = myTestClient.Operation_1(myTestRequest);

                Console.WriteLine("***************************");
                Console.WriteLine("*** Mult Result ***");
                Console.WriteLine("***************************\n");
                Console.WriteLine("Is: " + System.Convert.ToString(myResult.result));
                int i = Console.Read();
            }
            catch (Exception ex)
            {
                Console.WriteLine("\nException Message : " + ex.Message + "\n");
                Console.WriteLine("Exception Source : " + ex.Source + "\n");
                if (ex.InnerException != null)
                {
                    Console.WriteLine("\nInner Exception Message : " + ex.InnerException.Message + "\n");
                    Console.WriteLine("Inner Exception Source : " + ex.InnerException.Source + "\n");
                }
            }
        }
    }
}



No comments:

Post a Comment