FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
XML & Web Services
THE SOFTWARE SIMPLIST

Web Services Wisdom.

by Udi Dahan

June 2006


June 29, 2006

On the structure of services


Continuing on my previous post on “SOA Testing”, I wanted to discuss the structure of a service before getting into how unit testing could be used. First of all, I’m going to assume that you are designing large-scale, coarse-grained, autonomous, business-level services rather than dinky little address lookup services. In this case, the business logic of your service would most probably take the form of a Domain Model, a la Evans DDD. If you don’t think that you have enough meat in the service to warrant a domain model, you almost definitely don’t have enough meat for a whole service.

I will not get into how you can unit test a domain model, since that topic’s already been covered elsewhere, but it is worth mentioning that if you haven’t unit tested your domain model, trying to unit test your service is just wasted effort.

Alright then – getting back to the structure of a service. Since a service communicates via messages/messaging (preferably asynchronous), the service needs something to handle the different message types it receives. These are its Message Handlers. A service will have (in most cases) a single message handler class for each message type it can receive. (Remember that a service can receive and handle messages that are owned/defined by other services – for instance if it subscribes for those events.)

There is also the issue of what a message is – or rather, a message schema. A schema has two parts to it, one logical, and the other physical. The difference between the two is that the same logical schema can have an XML based physical manifestation, or a binary one, or a simple CSV/text based representation. While we may choose to use XML to represent our schema in a web services environment, most platforms eventually transform this representation into several classes, usually one class for each message type (inheritance and all that garbage aside). These platform level transformations belong in the bus. Message handler classes should only be aware of the logical schema represented in the platform those classes are implemented in. For example, the class that handles new order messages may be defined like so:

public class NewOrderMessageHandler : IMessageHandler
{
public void Handle(NewOrderMessage message) { … }
}

Notice how the class is dependent upon the platform specific representation of the message. The description “platform specific” doesn’t do the issue justice, since the “NewOrderMessage” class is just a “POJO” – a class that depends on nothing else but the specific runtime. The NewOrderMessage contains all the Integers, Doubles, Strings, etc that make up the order information. The business logic that understands the meaning of all the data in the message, as well as how to interact with the domain model in order to validate and process all parts of the order would be defined in the “Handle” method above.

So, since all the “Service Logic” is contained in message handlers, if you wanted to unit test a service, you would just go about unit testing its message handlers. And for all the zealots out there, no, you don’t have to test the transformation from XML to the platform specific classes. It adds no value.

Just to sum up, and my next podcast (#4) will go into more detail, message handlers are the “Service Layer” (aka Application layer) of DDD. It would be perfectly alright to call them in-process directly in a non-distributed hosted environment. This makes message handlers very suited for the in-process kinds of unit tests that are in such wide-spread use.

In my next post, I’ll describe how the message handlers get wired into the bus in such a way that leaves them independent of all the XMLy goo.

Posted by Udi Dahan at 03:08 PM  Permalink |


June 22, 2006

Reliable Messaging, Transactions, and Messages – oh my!


We’re going to keep steering clear of the SOA hype and FUD that’s been hitting the fan all over and deal with some real issues.

We’ve all heard about WS-Reliable Messaging, some of us have even read the spec. I’m pretty sure that the same goes for WS-Atomic Transaction. I’d say that most of us that build systems today pretty much ignore these specs and use what our tools give us today. The problem is that today’s tools don’t really point us in the right direction.


First let’s start with reliable messaging. There are really two kinds of messages in the world, those that we need to get to their destination (or know if they don’t), and those that we don’t really care either way. An example of a message type that would probably require reliable messaging would be something like a “ProcessOrderMessage”. An example of a message type without any reliability requirements would be something like “StockPriceUpdated”.

Let’s just ignore WS-Atomic Transaction for now (for ever wouldn’t be that bad either) and continue the discussion above in the context of transactions.

One of the purposes of reliable messaging is to ease the handling of failure scenarios. It’s so much easier to just send a recoverable message than code up retry logic to handle hardware failures. However, it’s obviously not enough for the message to reach its destination safely – we need to make sure that the message is also handled safely. This means that the entire process of retrieving the message from the queue, handling it (writing to the database), and sending other messages out occurs all together, and succeeds or fails as a whole. And if the process does fail, then the message needs to go back to the queue.

So, how does this connect with the higher-level concepts of SOA?

Well, consider this: If we define message types as either reliable or not, and we can only tell if we need to handle a message reliably (in a transaction) after we’ve already taken it out of the queue, and handling a non-reliable message in a transaction is a waste, we’d get the best performance by separating reliable and non-reliable messages into different queues/channels. We’d also like to be able to tell the infrastructure that retrieves these messages (the bus) which kind of behavior we want.

The final result is that we have identified a technological fracture line within services that enables us to distribute a given service over multiple servers without breaking its cohesion. Clients don’t need to know anything about the transactional nature of the message handling. They DO need to know if a message type needs to be reliable. If I was using WSDL, I would bemoan the fact that there is no easy way for me to do this.

Reliability is not an aspect you overlay or not on various instances of a given message type or different message types – it’s part of the contract. Transactions on the other hand, have no place in the contract – or between services for that matter. WSDL limits us by tying messages in the same contract to the same endpoint, although the runtime characteristics of those different message types should be different.

Vendors! Stop adding new, useless features to your products and fix the ones that are already there!

Posted by Udi Dahan at 03:06 PM  Permalink |


June 13, 2006

SOA, ESB, and Events — No 2.0


Expanding on my recent podcast, I wanted to add a word or two on the EDA (or Event Driven Architecture) buzz that popped faster than anything I've ever seen before and was replaced as SOA 2.0. Events are an integral part of any loosely coupled design. Mapping them to the SOA world, when using the vendor-generated web services tools didn't (and still doesn't) seem to fit. Maybe that's where people thought they could slip in a 2.0.

However, since we've already understood that the only things that pass between services are messages, then a message embodies an event as well. All we have to do is take care of the whole publish/subscribe semantics and technology. Simple, right?

Actually, it isn't that hard.

In the podcast, I describe using the abstractions introduced in the bus pattern/design to take care of the semantics. You want to subscribe to the Order Cancelled event of the Order Fulfillment service? Just implement the interface IMessageHandler<OrderCancelledMessage>. When the bus will see that handler, and it knows that the OrderCancelledMessage is owned by the Order Fulfillment Service (available at an endpoint different than your own), then the bus knows it needs to subscribe to that message with the service. One way it can do that is by sending a subscribe message to the service. The bus layer of the service will handle that message without passing it up the stack.

So far I haven't said anything new.

The important thing to see here has to do with contracts. If Service A wants to subscribe to messages of type X from Service B, does that make X part of Service A's contract? Of course not! So why do today's vendor implementations automatically cause that to occur? Just because a service, or a client for that matter, handle certain types of messages that doesn't say anything about their contract. If you look for the most recent technology stack coming out of any vendor targeting SOA you'd probably find Microsoft's Windows Communication Foundation (WCF - formerly known as Indigo). First of all, the fact that WCF poorly supports this core principle of SOA is incomprehensible. To top it off, it causes exactly the same effect as older stacks when it comes to Events (separate from OO level "events").

After doing a number of successful SOA implementations, I can tell you that the vast majority of service to service communication is event based, while running at around 40% for client to service scenarios. If you find that message types that are defined by numerous services, in the best case all you have is a technology that doesn't support events well; in the worst case, your service boundaries could be wrong.

Events really are the backbone of an SOA. The bus pattern/design supports events naturally. Don't settle for less.

Posted by Udi Dahan at 03:57 PM  Permalink |


June 09, 2006

[Podcast] Does an SOA require an ESB?


The number of products appearing in the ESB category is exploding, although their value remains unclear. What exactly is a 'bus' and is it really necessary that loosely-coupled services communicate through it? (MP3, 19:52 mins.)

Udi analyzes autonomous services, asynchronous messaging, and the bus architectural pattern.

Also read Udi's blog post: "Can Indigo be my bus?"

Podcast online here.

Posted by Udi Dahan at 06:02 PM  Permalink |


June 08, 2006

SOA Testing


The question of testing has been gaining quite a bit of traction lately in the whole SOA context. The catchall question, “how do I test my SOA?” is much too generic though.

First of all, we have to specify what kind of testing we’re talking about. Functional, non-functional, load, usability (services can have a UI) – each is approached differently. Second, we have to define what it is we’re testing. Are we trying to test the architecture, as the term “SOA testing” suggests, or are we focusing on testing a specific service?

Practically, architecture cannot be tested. The most common “test” performed on architecture is an inspection of use case realizations. By examining the way the system is going to be used in various scenarios, and tracing the flow through the elements that comprise the system, we can get a feel for how well the architecture supports a use case. If we see that a certain use case realization is cumbersome, or involves parts of the system that do not appear to be directly related to the use case, we might say that we found a bug in the architecture (if we really tried to use testing terminology). However, this process is really just a part of coming up with the architecture in the first place, before a single line of code is written. This doesn’t seem to jive very much with the spirit of “SOA testing”.

So, we’re back to how to test a specific service, once we decide what kind of testing we want. If we look at one of the important changes services brought to the structure of a system we can see that services represent a different style of division of functionality than components or objects. Their interfaces are different – message based. They manage their own data; which means we have to include state-based testing. When it comes to load testing, or usability testing, its hard to see what impact the decision to divide a system up into services (instead of components) has.

So, given that we’re going to want to perform functional, state-based testing on our services, we’re going to have to “exercise” them using the same kinds of communication found in a production environment – by using a bus, be it ESB or otherwise, to send to, and receive messages from the service under test. There’s also another level of testing that warrants examination in the service landscape and that is unit testing. What parts of a service can be unit tested, and how?

All the details, and more, coming soon :)

Posted by Udi Dahan at 04:48 PM  Permalink |


June 04, 2006

ESBs improve SOA testability


In my latest podcast I tried to describe the value that the bus architectural pattern can bring a distributed system. You can also find a link there to a detailed analysis of the API of a bus, and how well Microsoft latest communications platform (WCF, formerly known as Indigo) fits in with that API. What isn't immediately apparent is how the use of a bus can affect how you test a service.

The important thing to note about using a bus in such a fashion is that your application logic is entirely decoupled from technology. Just as important is that modeling of the message handler as the primary abstraction for encapsulating that application logic. In a supporting role, we find the message schema is a group of “plain old {your language here} objects” and independent of the XML representation on the wire.

In this design, we do not even require a bus in order to test our application. By encapsulating the application logic behind message handlers, we are now able to write application level tests just as if they were unit tests, and even run them using the same infrastructure (xUnit).

The result is striking. By isolating the message handling logic from communications details (like HTTP), we make it easier to write tests. This, in turn, results in more, higher quality tests that run faster – decreasing the time programmers need to wait for feedback.

Shorter timelines. Higher quality. Technological independence.

What’s the catch?

Well, this paradigm of messages and message handlers get muddled when multiple services handle the same kinds of messages – not to mention it introduces implicit dependencies between those services. The answer is: just don’t do that. There’s no reason two Autonomous Services should share the same schema. Since each Autonomous Service provides unique business value, there should be no overlap. In the cases where it appears there must be, the answer most often lies in switching to asynchronous communication.

The case where two Autonomous Services appear to share part of a schema most often occurs when you want data to pass from one to the other. One way to do this is to have those common messages be, indeed, common. Another, better, way is to have the consuming service subscribe to those messages published by the producing service. I’ve found this event-based, pub/sub pattern to best maintain the autonomy of each of the services.

So, there’s no real catch, if you get your boundaries right.
[Posted here as well.]

Posted by Udi Dahan at 05:13 PM  Permalink |



November 2007
Sun Mon Tue Wed Thu Fri Sat
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  


BLOGROLL
 
INFO-LINK