Since publishing my recent article on Next Generation Grid Enable SOA and taking this topic out into the world, I have been getting asked to clarify and frame the discussion around why state management in what is supposed to be “stateless” SOA is such an important issue. Steve Jones of CapGemini bluntly stated No they ruddy well shouldn’t be when he wrote his opinion on stateful vs stateless services in a SOA.
My observation has been that the need for state management is a continuum that ranges from completely stateless to fully stateful services as the complexity of the business logic and the longevity of the service instance increases.
I’ll define service state, btw, as the transient in-flight data that is required to be maintained across multiple requests to the same service, shared between duplicate instances of a service (for load-balancing or HA), or shared across multiple services that cooperate with each other in a business process
The following diagram illustrates the continuum:
The range begins with stateless services, which exhibit the same behavior and yield the same result whether called once, or 100 times. Different service clients can access and share the same service and each subsequent call into a service leaves nothing behind to affect the next service call. This is the easiest approach for simple services, but can become more challenging as the service logic becomes more complex.
As the service implementation progresses in complexity and and longevity, cookies + servlet session techniques are commonly used. This is by and large managed by the web container yet begins to introduce coding complexity as Java or .NET services need to pick apart the request properties (the “state” or “context”) using an API, then reinsert any new state into the response or outbound message. This begins to overlap into the next level of complexity, which is -
State passing via XML payloads - In this model all of the service state is packaged up into an XML message as header or body information, and either passed back and forth between client and service, or passed along from one service to the next. Within the context of the BPEL engine, much of this is hidden and automated. However, if the BPEL engine is calling out to external services then the model is much like the cookie/session model, where Java or .NET services need to pick apart the request properties (the “state” or “context”) using an API, then reinsert any new state into the response or outbound message. This for the most part allows the true core of the business logic to remain stateless yet there is still the overhead of the setup and tear-down of every request going in and out of the service. This state-passing model only works if the rules of engagement between the different layers are well known by all developers and are strictly adhered to. The average programmer is accustomed to the more conventional approach of coupling behavior and state into a single object.
The next level of complexity is what I call hard-wiring a shared context database - This is a pattern most often utilized where managing service state with full transactional integrity across multiple service requests is a must. Rather than passing state in the message, the service logic reads and updates all of its state data to a database between every request. This increases the footprint of the service, introduces a new dependency on the DB, and increases the workload on the DB in that it is now responsible for managing transactions of transient data (which may be very different and of much higher volume of longer term storage).