Jim's post got me thinking... Wouldn't it be nice to have Cw code generated automatically that captures the semantics of a Web Service contract? Please note that I am not talking about just converting WSDL to WebMethods and C#. We have something else in mind... We want to capture entire conversations and help the programmer deal with them. This is all about capturing the entire semantics of a protocol (i.e. a state machine). Could chords be used to do that? (After talking to Jim via IM, he confirmed to me that this is what he too had in mind in the context of our current work about which we should be able to talk soon).
Disclaimer : For the purposes of this post I am ignoring issues related to scalability of service implementations and the use of backend stores to manage interaction state. This post is just my current thinking which happens to use Cw as a vehicle.
So, here's a simple interface of a service implementation that is conversation-aware.
public class Service {
public async Msg1Arrived(Soap msg1) {...} public async Msg2Arrived(Soap msg2) & async Msg1Arrived(Soap msg1) {...} public async Msg3Arrived(Soap msg3) & async Msg1Arrived(Soap msg1) {...} public async Msg4Arrived(Soap msg4) & async Msg2Arrived(Soap msg2) {...} & async Msg3Arrived(Soap msg3) {...} }
The idea here is that Msg2Arrived() would be called only if Msg1Arrived() has been called first. Of course, if a Msg2 arrives before a Msg1, it will be queued until a Msg1 arrives (hmm... I am not certain whether we really want to wait forever though).
Also, Msg4Arrived() can only be called only after Msg2Arrived() or Msg3Arrived() have been called allowing different code blocks to be executed depending on which is the case.
(If someone knows Cw, please correct me if I am wrong here).
The problem with the above class for a service, however, is that it doesn't take into consideration the context/scope of an interaction. What if two Msg1s arrived before the first Msg2 arrives? With which of the two does Msg2 relate? What's the scope within which Msg2 should be dealt with?
If there is some way of distinguishing context/scope (e.g. WS-Context, WS-ReferenceProperties from WS-Addressing... not recommended!) then the infrastructure could automatically create instances of the above class to deal with instances of conversations. The implementation wouldn't have to care about distinguishing between implementations.
However, this means that interaction scope is managed by the infrastructure. In some cases, this approach could be inflexible. What if the interaction scope was determinable only through the application of some service-specific logic on the contents of the arriving message? For example, if an "order id" field in the body of the message determined the scope?
We can either assume that there is a way to pass an expression to the infrastructure that can be evaluated with the arrival of every message or manage the conversation context ourselves. The former could be achieved through various means (e.g. delegates, XPath queries if we know the structure of the message, declarative means in a contract language ;-). The latter could also be easily implemented (e.g. through a static hashtable) but we'd loose infrastructure support for server farming and the use of backend stores, unless we implemented such functionality ourselves (but we had lost infrastructure state management already by associating conversation state with object instances when we used Cw chords to model state transitions... unless Cw chord-related state is serialisable somehow... hmmm).
(I am also trying to figure out a way to implement support for different conversations through Cw without using objects (e.g. a Hashtable) to store state. It's proving difficult. I need to read the Join calculus.)
Can't wait to talk about what we are working on 🙂
2 responses to “Capturing a service conversation using Cw”