I’ve been working on a demo to present at a Microsoft practise meeting which is going to be held in a few days at the consulting firm where I’m employed. What started out as a simple demo turned into an enhanced solution so I thought I might as well wrap things up by a blog post to document what I’ve done.
This blog post covers the following .NET middleware technologies:
- Windows Azure Service Bus
- Relay Service
- Windows Server AppFabric
- Monitoring / Persistence
- Distributed Cache
- AppFabric Connect
- WCF Routing .NET 4.0
- Windows Workflow 4.0
The source code for the solution can be downloaded here.
1. AzureLOB.SubmitOrderClient - A WPF application is used by consumers to fill out and submit order requests via he Windows Azure Service Bus to an on-premises IIS hosted WCF Service. I’ve taken the client application from the Windows Azure Training Kit (Connecting a WCF Service in IIS 7.5 to the Service Bus), but modified it to suit this scenario.
2. AzureLOB.IISHostedWcfService / AzureLOB.WcfRoutingService – A WCF Service hosted in IIS must be configured to use Windows AppFabric Auto-Start feature in order to start receiving messages from the Service Bus in the cloud (the Relay Service). Wade Wegner explained in detailed in his blog post; Host WCF Services in IIS with Service Bus Endpoints, so this is out of scope for this article.
Upon receiving a request from the Service Bus in IIS, the request is simply forwarded to a WCF Routing Service. Based on the quantity ordered (Content Based Routing), the WCF Routing Service is responsible for routing the request to one of two WCF Workflow Services. You can read more about WCF Routing in this blog posts; WCF Routing Service Deep Dive: Part II–Using Filters, by Richard Seroter.
The routing service routes messages based on the following filter expressions in web.config.
<filters>
<filter name="OrderAcceptedFilter" filterType="XPath" filterData="//custom:Quantity <= 100" />
<filter name="OrderApprovalFilter" filterType="XPath" filterData="//custom:Quantity > 100"/>
</filters>
You may have noticed that there is room for improvement here. I would rather have the WCF Routing Service exposed to the Service Bus directly, without having a service fronting it, however I haven’t manage to solve this just yet.
3, AzureLOB.OrderAccepted.WorkflowService – Order requests with quantity less or equal to 100 are routed to an “accepted” Workflow Service. This WCF Workflow Service sends a response back to the client, via the Service Bus, indicating the id and status (ACCEPTED) of the order.
The workflow saves its state to the Windows Server AppFabric Persistence Store just before sending the response back to the client. Later, if an exception occurs during the life cycle of the workflow, for instance if the downstream system is temporary unavailable, it is possible to resume the workflow from this execution bookmark once the downstream system is back up again.
Enable AppFabric Persistence for Workflow in IIS.
Resuming a suspended workflow instance from the AppFabric Dashboard in IIS.
The workflow ends by committing the ACCEPTED order to the database.
4. AzureLOB.OrderApproval.WorkflowService – Order requests with quantity greater than 100 are routed to a long-running WCF Workflow Service. Again this workflow persists itself to the AppFabric Persistence Store before sending the id and status (PENDING) of the order back to the client.
Orders routed to the order approval workflow must manually be finalised. The long-running workflow initially submits the order with a PENDING status to the database.
Using correlation the workflow then waits until a subsequent order approval message (submitted by the Approver in the diagram) is received.
Pending order awaiting approval.
You can read more about correlation in workflows here: Correlate Multiple Receive Activities.
5 – 6. Both WCF Workflow Services use AppFabric Connect to communicate (insert and update) with the database. You can read more about AppFabric Connect here: BizTalk + WF/WCF, Better Together.
7. AzureLOB.OrderManagementClient – The Approver sends a request to a WCF Service to retrieve a pending order for approval.
8 – 9. AzureLOB.CachingService – The caching service is a WCF Service that utilises the AppFabric Distributed Cache to maintain a collection of cached pending order objects. The WCF Service initially makes a call to check if any pending orders exist within the cache. If no pending orders are found the WCF Service populates the cache with a collection of all pending orders retrieved from the database. The client application will subsequently only receive cached objects until no pending orders are present within the cache. The WCF Service will then need to make a new call to retrieve orders with status PENDING from the databases and populate the cache.
When using the AppFaric Cache you should keep in mind that the database is always your source of truth and that the cache cannot be relied on as a secure store provider, it is a non-transaction cache. When designing something like the above you should take into account that a possible unexpected failure might occur within your solution.
10. AzureLOB.OrderManagementClient – A pending order is either accepted or declined and submitted to a correlating workflow instance to be finalised.
11. AzureLOB.OrderApproval.WorkflowService – The workflow updates the order to its final status (ACCEPTED/DECLINED) in the database. Ultimately, this implies that the end of the long-running workflow and closing the pending order.
Please understand that this is a demo. Some portions of the solution might be overkill or implemented in an easier way. For instance there is really no reason for having two workflows in this scenario. What I’m trying to demonstrate here is the ability to do content-based routing in WCF and show how backend Line of Business systems like SQL Server, SAP, Oracle, and Seibel can be fronted with workflow services to ensure reliable messaging. Using AppFabric Connect the demo can easily be extend to send all accepted orders to an Oracle database, for instance.
I’m playing around with the idea to push the order messages to an AppFabric Queue instead of using a Relay Service and perhaps make use of the Azure AppFabric June CTP to ”cloudify” the solution (some question marks here and there but I’m sure it’s solvable).
What you need to run the demo:
- A Windows Azure Account and a registered AppFabric Service Bus Namespace
- Visual Studio 2010
- SQL Server 2008 or later with Chinook database. A colleague of mine is using the Chinook database to do a demo on SQL Azure and we thought it would be nice to use the same database. You can download the Chinook database here, you then need to execute the SQL script in the AzureLOB solution to create the Order table.
- IIS 7.5
- Windows Azure AppFabric SDK V1.0
- Windows Azure SDK 1.4
- Windows Server AppFabric with Persistence Store and Caching Service configured
- BizTalk Server 2010 with AppFabric Connect installed