Q & A on Advanced Workflow Services talk

Martin posted an interesting question here on my last post:


The first thing that we need to do in order to enable this duplex messaging to occur is that the "client" workflow has to explicitly provide its context token to the service so that the service can address the appropriate instance of the client workflow.

Note, in the real world, you’ll probably need to supply more than just the context token, you will need some address and binding information.


Shouldn’t we have this built into a custom binding? (or an extra binding element) So with every call from the client the (WF)context information is included. And the developer is not required to follow a (artificial) state machine.

Note, at the time, when the service calls back, the endpoint (and the binding) of the client may have changed… So we may need dynamic name-endpoint resolution (sounds like DNS?)


The question here is generally also asked as "wait, why do I need to explicitly provide a context token and change the contract to have this context thing?"  This is a common question, as changing the contract to reflect implementation details is generally a no-no.  There’s one part I left out as well, so let me add that here:

In the real world, one may also wish to not change the contract (or may not have the ability to).  In that case, we still need to explicitly provide the context token and endpoint information in order to allow me to call back.  There are a few ways to do this, of varying complexity and implication:

  • Put this into the message header and have the other side extract this information and use it the same way.
    • There are two downsides to this approach:
      • It still requires management of the other side to agree upon where the context token is being place.
      • The WF Messaging activities don’t give me an easy way to reach in and get to header information, but one could certainly look at some infrastructure level extensions to manage this.  This idea of making duplex easier is one thing that Ed will be talking about in his Oslo workflow services talk at PDC
  • Create a custom binding element.
    • There is one downside with this approach:
      • You’re creating a custom channel, custom binding element, and all the other stuff that goes along with creating a channel.  This is very hard work.  If the answer is "you’ve got to write a channel to do it," we need to do a better job making it easier (see earlier point about Ed’s talk).
    • If that’s the behavior that you want, you are certainly welcome do go down that path, it would be great to hear about your experiences doing it!
    • The upside to this approach:
      • You’re creating a layer of near infinite extensibility, allowing you to handle simple things to the complex dynamic endpoint resolution behavior, once you invest the cost once to create the channel that would sit there and do that.

This is also the same approach one could take with using an implicit, or content based correlation scheme.  In that case, you create an intermediary that is responsible for translating message contents into the "addressing" information for the instance.  That intermediary can be a service, it could be a channel, and once you put that intermediary in place, you are free to do as sophisticated or as simple work as possible.

Comments (1)

  1. andersonimes says:

    Definitely too hard and not service-oriented.  I like the idea of sending it via the headers or some other such implementation, but that would also require implementation on the other side in the form of an agreed-upon place and format of the context information or a custom binding implementation that you either distribute or have the other side of the fence reimplement.

    The first time I did this I spent days working on it saying to myself "surely you don’t have to do this… surely you don’t have to tell the target service which *activity* you want it to talk to next".  But you do.  It makes me sad inside.

    One thing I’ve not seen implemented yet in a demo.  I really like the feature of State Machine super states and substates.  The ability to take a group of 3 states and put them in another state called "Cancellable" or some other such interrupty business function is really kickass.

    Let’s say you are in state "Processing" which has an event-driven that listens for the service method "FinishedProcessing".  "Processing" is also in a superstate called "Cancellable" with an event-driven that listens for "CancelProcess".  How could you implement this when you have to tell the other service about the context identifier of the target receive activity?  Do you have to send both contexts?  I fear your answer will be yes.