Adopting, designing, and governing SOA well

SOA Best Practices Digest

Subscribe to SOA Best Practices Digest: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get SOA Best Practices Digest: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


SOA Best Practices Authors: Jason Bloomberg, Hollis Tibbetts, Pat Romanski, Liz McMillan, Lori MacVittie

Related Topics: SOA Best Practices Digest, SOA & WOA Magazine

SOA Best Practices: Article

SOA Patterns: Basic Structural Patterns – Part 2

The Transactional Service Pattern

It is important to notice the difference between setting the transaction scope from the endpoint/edge onward or setting it from the sender, which is external to the service. The difference may not seem important, but it is - since in the former case you increase the reliability of the service and the latter case increases coupling in the system and can cause you a lot of headaches. When you extend a transaction beyond the service boundary, you are making a leap of faith since the other service runs on its own machine, it has its own SLA, etc. Holding internal resources for something beyond the service trust boundary is risky.

Let's look at what's needed to implement a transactional service.

Technology Mapping
The technology mapping section takes a brief look at what it means to implement the pattern using existing technologies and mentions places technologies implement the pattern.

Implementing a Transactional Service can be easy if the message transport is transaction aware. Examples for transaction-aware infrastructure can be found in most ESBs such as Sonic ESB and Iona Artix, and also in messaging middleware like MSMQ, any JMS implementation, or SQL Server Service Broker. If you are using a transactional message transport, you can implement the Transactional Service Pattern by just creating a transaction on that resource. You may need to make the transaction distributed if, for example, you also perform database updates within the same unit of work. Then you just read a message from the ESB or messaging middleware, process it, send reactions or other  messages generated by the process to outgoing or destination queues, and commit the transaction, if everything was successful.

Note that since you would usually use more than one resource in the transaction, for instance, a queue for the message and a database to save any state changes after handling that message, you will most likely need a distributed transaction. In .NET 2.0 and up you can open a TransactionScope object (defined in System.Transactions) to transparently move to a distributed transaction if needed.

If the message transport doesn't support transactions, only acknowledge after you've saved the message into some transactional repository such as a queue or a table. You still run the risk of handling a message without acknowledging the service consumer, so you need to be ready for the possibility of getting the request again in case the ack was lost or never sent. In case of a failure, you will also need compensation logic if you sent messages to other services within the transaction that handled the incoming message.

Poison Messages
When we read a message in a transactional manner, we need to pay attention to identify and handle poison messages. A poison message is a message that is faulty in some way that makes the service crash or always aborts the transaction when it is handled. The problem is that if you read the poison message inside a transaction, the crash causes the message to return to the queue, where it nicely waits until your service recuperates enough to read it again and repeat the cycle. Some technology options like messaging products may have a mechanism to identify and discard poison messages. You need to make sure the mechanism is there and that it takes care of all your crash scenarios or at least be aware of this and deal with it yourself.

A technology that seems related is WS-ReliableMessaging. However, despite its name, the protocol is only concerned with delivering the message safely from point to point; in a sense WS-ReliableMessaging is sort of like TCP for HTTP. There is no durability promise or any transactional trait imbued in the protocol. Many ESBs, which are transactional, support this protocol so you can have the best of both worlds of using a standard protocol and transactional handling of messages.

Other related protocols are WS-Coordination and its "siblings" WS-AtomicTransaction and WS-BusinessActivity. Let's focus on WS-AtomicTransaction. WS-AtomicTransaction basically defines a protocol to orchestrate a distributed transaction between services. As a general rule I would not recommend using this as it introduces a lot of coupling between services. For instance, in the scenario in Figure 8 - do we really want to lock resources while we wait for the supplier that is external to our company and may, for example, treat our orders with low priority?

When you use a transaction-aware middleware the situation is a little different. Instead of one transaction that spans between services, you have three little transactions, one that the sending services and the middleware performs internally to guarantee delivery and the last one between the middleware and the reader - this is a coupling to the infrastructure that you can isolate in an Edge Component.

Quality Attribute Scenarios
The quality attribute scenarios section talks about the architectural benefits of utilizing patterns from the requirements perspective. Most of the architectural requirements are described from the perspective of quality attributes (scalability, flexibility, performance etc.) through the use of scenarios where these attributes are manifested. The scenarios can also be used as references for situations where the pattern is applicable.

The transactional semantics that Transactional Service induces can simplify both coding and testing. In addition, it can greatly enhance the reliability and robustness of the service. The code becomes simple since the promise of "all or nothing" helps keep developers focused on delivering the business value rather than thinking about edge cases and other related distractions.

Here are a couple of examples for scenarios that can point you to looking at the Active Service Pattern.

Quality Attribute (level1)

Quality Attribute (level2)

Sample Scenario

Reliability

Data lows

under all conditions, a message acknowledged by the system will not be lost

Testability

Coverage rate

get 95% or better  test coverage for all scenarios

The Transactional Service Pattern saves us coding because transactions don't have as many edge cases as you have when you write non-transactional code. Another pattern that can save writing code is the Workflodize Pattern, which is discussed in Part 3.

•   •   •

This article is based on the book SOA Patterns (http://www.manning.com/rotem) scheduled to print February 2009. This article is courtesy of Manning Publications (http://www.manning.com). The ebook is available and sold exclusively through Manning Publications.

More Stories By Arnon Rotem-Gal-Oz

For the past 10 years Arnon Rotem-Gal-Oz has been an architecture and system designer of large distributed systems including C4ISR systems, IP customer care and billing systems, and BI engines. He has experience with a variety of technologies (.Net, J2EE, CORBA, COM+, X-Windows) on diverse platforms (Unix, Windows, Dos, AS/400). He currently works for Rafael as the Biometric line development manager.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.