NetShock Blog
Wednesday, April 1, 2009

Practical SOA using WCF

These days there's a lot of talk about cloud computing, Web 2.0 and SOA (or SaaS), but too often they are thrown around as merely buzz words in an evolving online economy.  The unfortunate outcome of this is that businesses are often confused by the real benefits of implementing these new concepts.

Many organisations we've worked with have attempted SOA but failed with the conceptual basis for it.  SOA or software-as-a-service is great as a marketing term, but how often do organisations actually implement this correctly?  Just slapping a service on your existing application or building one fat service that encompasses the entire application is certainly not the answer; however, the majority of vendors are still not providing the complete set of tools required to do this the right way.

SOA is primary about boundaries, as should be most software development.  The most vital aspect of implementing this architecture correctly is knowing your boundaries and sticking to them.  This is in stark contrast to the oh so often "do whatever is needed to get it working" attitude of software development (especially in web development).  An architect must decide on strict boundaries for each service (or component) of an application.  With this in mind, an architect must also be mindful of service reusability (there's no point building a "Customer" service for one application if it won't fit a customer service in another application for the organisation).

So how do we practically build SOA?  Let's take a simple warehousing application as an example.  Let's define the requirements of this application:

  • Store the products that are available in the warehouse
  • Track their inventory and statuses
  • Manage customers who use the warehouse
  • Track orders for products in the warehouse
  • Track the shipment of these orders

Just with those requirements alone, one can almost elicit the services that will be required to create a properly architected solution.  The services would be:

  • Catalogue service (containing all the products in the warehouse)
  • Inventory service (containing information about the stock availability of the products)
  • Customer service (containing information about all the customers)
  • Order service (handling orders for the specified products)
  • Shipment service (tracking shipments for the orders)

The most common mistake would be to either create too many services, or too few.  For example, combining the order, inventory and shipment services into a single "warehouse" service would break the architecture in that the service would be rarely reusable and is product-specific.  While product-specific services are sometimes required, they should be avoided at all cost.  Remember, services should be agnostic of the product in which they are being used.

The bigger question is how are these services linked (or coupled) together?  That really comes down to two aspects - architecture and implementation.  The latter is dependent on your vendor of choice - in our case, Microsoft's WCF.

Your two choices would be EDA (event-driven architecture) or a "product" service.  The former is the preferred method as the latter creates a single service (providing a potential single point of fail) which orchestrates interaction between the various services.  The former is an architecture based on services publishing certain events which other services may subscribe to.  Microsoft also provides BizTalk and WF (Windows Workflow Foundation) which provides a workflow-oriented way of orchestrating service interactions.  This, however, still provides a single point of failure.

In this blog, we'll tackle the EDA approach.  WCF provides a basic publisher/subscriber model for its services, but unfortunately has some significant pitfalls.  To exchange messages in this manner, subscribers must always be "connected" to the publisher to receive messages.  In an instance of disconnection or failure, subscribers would simply stop receiving messages.  This is not an option in any reliable system.

To tackle this, one must create their own "permanent" publisher/subscriber model by building on WCF's existing model.  This is done by storing endpoints in a persisted form (e.g. in a database) and publishing the necessary messages directly to these subscribers.  By using MSDTC (Microsoft Distributed Transaction Coordinator), one can safely rollback transactions if a subscriber is unavailable (thus ensuring data integrity).  There are SOA purists out there who oppose the prospect of an essentially "cross-service" transaction coordinator, but we are talking about practical SOA.

Certain services require loose knowledge of external objects.  For example, the "Inventory" service must know what products it's tracking, so it would subscribe to the AddProduct, UpdateProduct and DeleteProduct events from the "Catalogue" service.  By the same token, the "Order" service essentially combines customers and products by creating an order - it must therefore subscriber to the former "Catalogue" events as well as the AddCustomer, UpdateCustomer and DeleteCustomer events from the "Customer" service.

These services should not replicate all the data from the events it receives.  It should only track the data it requires for it to function, thus fitting with the SOA model of strict boundaries.  The order service shouldn't have the customer's details as that's not its job - it's not supposed to be tracking customers, just orders.

Of course, many other events would be published.  The "Order" service may publish the "OrderReceived" to which the "Inventory" service would subscribe (to track the reduction in stock levels).  These events should be architected at the beginning of any application lifecycle.

After successfully implementing this architecture, an organisation would have a highly maintainable and scalable warehousing application.  Furthermore, they now have five organisation-specific services which could be reused to create a completely separate product (for example, a shopping cart, stocktake system, auction system or even the start of a CRM).

This is a practical way of implementing SOA correctly by using WCF and EDA.  Software-as-a-service is not just a marketing term, but it can be very poorly implemented without the correct architecture and create more problems than it solves.  When your organisation does choose SOA, be sure to have the right architecture!