Rationale for Compensating Service Transactions

March 5, 2011

Compensating Service Transaction pattern helps consistently handle composition runtime exceptions while eliminating the need for locking resources.

Service compositions could generate various runtime exceptions as part of fulfilling service functionality. For example, imagine a service composition that invokes a decision service to validate request data, proceeds to update a customer entity via an entity service, and then sends a message on a queue for an external process to consume. Consider the three steps as part of a single unit of work – a service transaction that execute in sequence.

If runtime exceptions associated with the composition are unhandled there is an increased likelihood of compromising data and business integrity. Similarly, if all the steps are executed as an atomic transaction each service invocation will tie up backend resources (e.g. using various kinds of locks) hurting performance and scalability.

The compensating service transaction pattern introduces additional compensation steps in order to handle runtime exceptions without locking system resources. These additional steps can be included as part of the composition logic or made available as separate undo service capabilities. Continuing the earlier example, a call to undo the customer update (essentially resetting the data back to the earlier state) can be made to place the underlying data in a valid state.

The Compensating Service Transaction pattern provides several benefits:

  • Eliminates the need for executing distributed service invocations within a transactional context.
  • Provides a mechanism for services/resources that don’t support atomic transactions to participate in service compositions.
  • Reduces load on underlying systems and databases by only invoking compensation routines when failure occurs. Instead of locking resources in case failures happen, the idea is to handle runtime exceptions when they actually occur.
  • Allows reuse of compensation steps across service compositions. E.g. two business services that update a data entity can reuse the undo Update capability.

Compensating transactions tend to be more open-ended when compared to atomic transactions and their actual effectiveness varies. The extent to which the service composition can apply this pattern is directly dependent on the undo capabilities provided by various service capabilities being invoked. Consequently, this pattern cannot be leveraged if compensating transactions don’t exist. Likewise, it is necessary to ensure that the compensating steps themselves execute successfully. Error alerts/notifications may need to be sent in case compensations fail and manual interventions are needed.

How Service Orientation Principles Guide Reuse

November 6, 2009

In an earlier post, I elaborated on agile principles that facilitate reuse. As a follow up, I want to emphasize how principles of service orientation do the same from a complimentary perspective.

Principle How is this supported? Why is this supported?
Loose Coupling Service logic is built independent of specific product, technology, channel, and transport. Legacy services are wrapped to avoid direct coupling between providers and consumers. Both techniques are performed iteratively using refactoring. Decouple horizontal concerns such as logging, error handling, metrics, security from core logic. Lower the coupling, higher the opportunity for service reuse. Promotes agility by making less assumptions about upstream and downstream dependencies. Gives flexibility to service provider for performing continuous refactorings. Reuse horizontal capabilities for non-service components in the codebase.
Abstraction Code reviews and refactoring used to simplify and consolidate service contracts that aren’t well abstracted. Applies to both legacy and new services in the domain inventory. Abstract common service needs using multiple iterations and user stories. Abstraction clarifies domain intent and reduces needless coupling between providers and consumers. It eliminates point to point coupling between legacy services and consumers facilitating graceful migration.
Composability Refactor both new code and legacy modules within iterations. Identify opportunities for compositions when brainstorming implementation options for user stories. Use design patterns such as template method to design orchestrations. Composability is key for high levels of service reuse for implementing task services.
Standardized contract Code and design reviews will be used to ensure reuse of data types, error codes, schema definitions, and that the contracts don’t expose implementation/technology specific details. If contract changes late in an iteration, add needed refactorings to iteration backlog and fix in a future iteration. A service is not “done,done” unless the contract is reviewed. Helps align contracts with logical data models for enterprise data entities. Delivers consistent behavior when a service is reused across physical transports. Helps create loose coupling among legacy interfaces and consumers.
Autonomy By decoupling legacy modules from being tightly bound increasing autonomy. Host services in a standard runtime environment. Autonomous services are easier to reuse both as standalone entities as well as in service compositions.
Statelessness Reuse strategy used to identify stateless services. Code reviews will identify and remove state that inhibits reuse. Stateless services offer higher degree of reuse and are simpler to scale to accommodate increased traffic.
Reusability Building reusable services that can be mapped to user stories. Using legacy services to implement user stories and code reviews to remove duplication across the service inventory. Iteration planning allocates time for wrapping legacy services, unit testing, and working on refactoring backlog. Release planning is performed to ensure services are built within the context of an overall reuse strategy and a real consumer. Use product line techniques such as to allow service variations to accommodate varying consumer functional and quality of service characteristics. Minimize service development without a real consumer. Facilitates iterative and incremental manner for building reusable services. As user stories become better understood and code reviews have been done future iterations are continuously used to refactor the service.

Do these resonate with how you approach SOA and service orientation while building reusable service capabilities?

Like this post? Subscribe to RSS feed or get blog updates via email.

tweet this add to del.icio.us post to facebook

SOA Success Is More Than Service Creation

June 26, 2009

I often talk to folks who believe that SOA is about creating services. While that is partially true it isn’t the complete picture. The goal of SOA is not service creation but business transformation. Creating a service is a necessary but not sufficient condition for SOA success.  You create services to orchestrate legacy capabilities, execute business rules, and manipulate enterprise data.

But, all these are done within the context of business objectives (at least you need to aspire to do that!)

Succeeding with SOA involves utilizing services – multiple kinds of services – to implement functionality, automate business processes, and achieve business objectives. As a by product if you follow reuse-friendly techniques and practices you will build up a service inventory that can be leveraged for future projects. But building up a service inventory isn’t the primary objective – it is a by product of executing SOA right. It means designing, implementing, productionizing, and governing services that are of value to your business, to your domain.

Like this post? Subscribe to RSS feed or get blog updates via email.

add to del.icio.us: Digg it : post to facebook: Stumble It! : :

%d bloggers like this: