<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Clemens Vasters - Architecture|SOA</title>
    <link>http://vasters.com/clemensv/</link>
    <description>Cloud Development and Alien Abductions</description>
    <language>en-us</language>
    <copyright>Clemens Vasters</copyright>
    <lastBuildDate>Tue, 15 Jan 2013 18:56:36 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.7067.0</generator>
    <managingEditor>cvasters@guhhome.com</managingEditor>
    <webMaster>cvasters@guhhome.com</webMaster>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=4718bf97-cc2e-46ba-854a-f4a1d93fb2a9</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,4718bf97-cc2e-46ba-854a-f4a1d93fb2a9.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,4718bf97-cc2e-46ba-854a-f4a1d93fb2a9.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=4718bf97-cc2e-46ba-854a-f4a1d93fb2a9</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://en.wikipedia.org/wiki/File:ESB.png">
            <img style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; FLOAT: right; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN: 2px 0px 2px 5px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" border="0" alt="File:ESB.png" align="right" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/ESB.png/751px-ESB.png" width="300" height="240" />
          </a>The
basic idea of the Enterprise Service Bus paints a wonderful picture of a harmonious
coexistence, integration, and collaboration of software services. Services for a particular
general cause are built or procured once and reused across the Enterprise by ways
of publishing them and their capabilities in a corporate services repository from
where they can be discovered. The repository holds contracts and policy that allows
dynamically generating functional adapters to integrate with services. Collaboration
and communication is virtualized through an intermediary layer that knows how to translate
messages from and to any other service hooked into the ESB like a babel fish in the
Hitchhiker’s Guide to the Galaxy. The ESB is a bus, meaning it aspires to be a smart,
virtualizing, mediating, orchestrating messaging substrate permeating the Enterprise,
providing uniform and mediated access anytime and anywhere throughout today’s global
Enterprise. That idea is so beautiful, it rivals My Little Pony. Sadly, it’s also
about as realistic. We tried regardless.
</p>
        <p>
As with many utopian ideas, before we can get to the pure ideal of an ESB, there’s
some less ideal and usually fairly ugly phase involved where non-conformant services
are made conformant. Until they are turned into WS-* services, any CICS transaction
and SAP BAPI is fronted with a translator and as that skinning renovation takes place,
there’s also some optimization around message flow, meaning messages get batched or
de-batched, enriched or reduced. In that phase, there was also learning of the value
and lure of the benefits of central control. SOA Governance is an interesting idea
to get customers drunk on. That ultimately led to cheating on the ‘B’. When you look
around and look at products proudly carrying the moniker ‘Enterprise Service Bus’
you will see hubs. In practice, the B in ESB is mostly just a lie. Some vendors sell
ESB servers, some even sell ESB appliances. If you need to walk to a central place
to talk to anyone, it’s a hub. Not a bus. 
</p>
        <p>
Yet, the bus does exist. The IP network is the bus. It turns out to suit us well on
the Internet. Mind that I’m explicitly talking about “IP network” and not “Web” as
I do believe that there are very many useful protocols beyond HTTP. The Web is obviously
the banner example for a successful implementation of services on the IP network that
does just fine without any form of centralized services other than the highly redundant
domain name system. 
</p>
        <p>
Centralized control over services does not scale in any dimension. Intentionally creating
a bottleneck through a centrally controlling committee of ESB machines, however far
scaled out, is not a winning proposition in a time where every potential or actual
customer carries a powerful computer in their pockets allowing to initiate ad-hoc
transactions at any time and from anywhere and where we see vehicles, machines and
devices increasingly spew out telemetry and accept remote control commands. Central
control and policy driven governance over all services in an Enterprise also kills
all agility and reduces the ability to adapt services to changing needs because governance
invariably implies process and certification. Five-year plan, anyone? 
</p>
        <p>
If the ESB architecture ideal weren’t a failure already, the competitive pressure
to adopt direct digital interaction with customers via Web and Apps, and therefore
scale up not to the scale of the enterprise, but to scale up to the scale of the enterprise’s
customer base will seal its collapse. 
</p>
        <h3>Service Orientation
</h3>
        <p>
While the ESB as a concept permeating the entire Enterprise is dead, the related notion
of Service Orientation is thriving even though the <a href="http://msdn.microsoft.com/en-us/library/ff648318.aspx#SOATenets">four
tenets of SOA</a> are rarely mentioned anymore. HTTP-based services on the Web embrace
explicit message passing. They mostly do so over the baseline application contract
and negotiated payloads that the HTTP specification provides for. In the case of SOAP
or XML-RPC, they are using abstractions on top that have their own application protocol
semantics. Services are clearly understood as units of management, deployment, and
versioning and that understanding is codified in most platform-as-a-service offerings. 
</p>
        <p>
That said, while explicit boundaries, autonomy, and contract sharing have been clearly
established, the notion of policy-driven compatibility – arguably a political addition
to the list to motivate WS-Policy as the time – has generally been replaced by something
even more powerful: Code. JavaScript code to be more precise. Instead of trying to
tell a generic client how to adapt to service settings by ways of giving it a complex
document explaining what switches to turn, clients now get code that turns the switches
outright. The successful alternative is to simply provide no choice. There’s one way
to gain access authorization for a service, period. The “policy” is in the docs. 
</p>
        <p>
The REST architecture model is service oriented – and I am not meaning to imply that
it is so because of any particular influence. The foundational principles were becoming
common sense around the time when these terms were coined and as the notion of broadly
interoperable programmable services started to gain traction in the late 1990s – the
subsequent grand dissent that arose was around whether pure HTTP was sufficient to
build these services, or whether the ambitious multi-protocol abstraction for WS-*
would be needed. I think it’s fairly easy to declare the winner there. 
</p>
        <h3>Federated Autonomous Services
</h3>
        <p>
          <a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Utopia-ESB_87DD/image_2.png">
            <img title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; FLOAT: right; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" border="0" alt="image" align="right" src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Utopia-ESB_87DD/image_thumb.png" width="240" height="213" />
          </a>Windows
Azure, to name a system that would surely be one to fit the kind of solution complexity
that ESBs were aimed at, is a very large distributed system with a significant number
of independent multi-tenant services and deployments that are spread across many data
centers. In addition to the publicly exposed capabilities, there are quite a number
of “invisible” services for provisioning, usage tracking and analysis, billing, diagnostics,
deployment, and other purposes.  Some components of these internal services integrate
with external providers. Windows Azure doesn’t use an ESB. Windows Azure is a federation
of autonomous services.
</p>
        <p>
The basic shape of each of these services is effectively identical and that’s not
owing, at least not to my knowledge, to any central architectural directive even though
the services that shipped after the initial wave certainly took a good look at the
patterns that emerged. Practically all services have a gateway whose purpose it is
to handle and dispatch and sometimes preprocess incoming network requests or sessions
and a backend that ultimately fulfills the requests. The services interact through
public IP space, meaning that if Service Bus wants to talk to its SQL Database backend
it is using a public IP address and not some private IP. The Internet is the bus.
The backend and its structure is entirely a private implementation matter.  It
could be a single role or many roles. 
</p>
        <p>
Any gateway’s job is to provide network request management, which includes establishing
and maintaining sessions, session security and authorization, API versioning where
multiple variants of the same API are often provided in parallel, usage tracking,
defense mechanisms, and diagnostics for its areas of responsibility. This functionality
is specific and inherent to the service. And it’s not all HTTP. SQL database has a
gateway that speaks the Tabular Data Stream protocol (TDS) over TCP, for instance,
and Service Bus has a gateway that speaks AMQP and the binary proprietary Relay and
Messaging protocols.
</p>
        <p>
Governance and diagnostics doesn’t work by putting a man in the middle and watching
the traffic coming by, which is akin to trying the tell whether a business is healthy
by counting the trucks going to their warehouse. Instead we are integrating the data
feeds that come out of the respective services and are generated fully knowing the
internal state, and concentrate these data streams, like the billing stream, in yet
other services that are also autonomous and have their own gateways. All these services
interact and integrate even though they’re built by a composite team far exceeding
the scale of most Enterprise’s largest projects, and while teams run on separate schedules
where deployments into the overall system happen multiple times daily. It works because
each service owns its gateway, is explicit about its versioning strategy, and has
a very clear mandate to honor published contracts, which includes explicit regression
testing. It would be unfathomable to maintain a system of this scale through a centrally
governed switchboard service like an ESB.
</p>
        <p>
Well, where does that leave “ESB technologies” like BizTalk Server? The answer is
simply that they’re being used for what they’re commonly used for in practice. As
a gateway technology. Once a service in such a federation would have to adhere to
a particular industry standard for commerce, for instance if it would have to understand
EDIFACT or X.12 messages sent to it, the Gateway would employ an appropriate and proven
implementation and thus likely rely on BizTalk if implemented on the Microsoft stack.
If a service would have to speak to an external service for which it would have to
build EDI exchanges, it would likely be very cost effective to also use BizTalk as
the appropriate tool for that outbound integration. Likewise, if data would have to
be extracted from backend-internal message traffic for tracking purposes and BizTalk’s
BAM capabilities would be a fit, it might be a reasonable component to use for that.
If there’s a long running process around exchanging electronic documents, BizTalk
Orchestration might be appropriate, if there’s a document exchange involving humans
then SharePoint and/or Workflow would be a good candidate from the toolset. 
</p>
        <p>
For most services, the key gateway technology of choice is HTTP using frameworks like
ASP.NET, Web API, probably paired with IIS features like application request routing
and the gateway is largely stateless.
</p>
        <p>
In this context, <em>Windows Azure Service Bus</em> is, in fact, a technology choice
to implement application gateways. A Service Bus namespace thus forms a message bus
for “a service” and not for “all services”. It’s as scoped to a service or a set of
related services as an IIS site is usually scoped to one or a few related services.
The Relay is a way to place a gateway into the cloud for services where the backend
resides outside of the cloud environment and it also allows for multiple systems,
e.g. branch systems, to be federated into a single gateway to be addressed from other
systems and thus form a gateway of gateways. The messaging capabilities with Queues
and Pub/Sub Topics provide a way for inbound traffic to be authorized and queued up
on behalf of the service, with Service Bus acting as the mediator and first line of
defense and where a service will never get a message from the outside world unless
it explicitly fetches it from Service Bus. The service can’t be overstressed and it
can’t be accessed except through sending it a message. 
</p>
        <p>
The next logical step on that journey is to provide federation capabilities with reliable
handoff of message between services, meaning that you can safely enqueue a message
within a service and then have Service Bus replicate that message (or one copy in
the case of pub/sub) over to another service’s Gateway – across namespaces and across
datacenters or your own sites, and using the open AMQP protocol. You can do that today
with a few lines of code, but this will become inherent to the system later this year. 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=4718bf97-cc2e-46ba-854a-f4a1d93fb2a9" />
      </body>
      <title>Utopia ESB</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,4718bf97-cc2e-46ba-854a-f4a1d93fb2a9.aspx</guid>
      <link>http://vasters.com/clemensv/2013/01/15/Utopia+ESB.aspx</link>
      <pubDate>Tue, 15 Jan 2013 18:56:36 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://en.wikipedia.org/wiki/File:ESB.png"&gt;&lt;img style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; FLOAT: right; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN: 2px 0px 2px 5px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" border=0 alt=File:ESB.png align=right src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/ESB.png/751px-ESB.png" width=300 height=240&gt;&lt;/a&gt;The
basic idea of the Enterprise Service Bus paints a wonderful picture of a harmonious
coexistence, integration, and collaboration of software services. Services for a particular
general cause are built or procured once and reused across the Enterprise by ways
of publishing them and their capabilities in a corporate services repository from
where they can be discovered. The repository holds contracts and policy that allows
dynamically generating functional adapters to integrate with services. Collaboration
and communication is virtualized through an intermediary layer that knows how to translate
messages from and to any other service hooked into the ESB like a babel fish in the
Hitchhiker’s Guide to the Galaxy. The ESB is a bus, meaning it aspires to be a smart,
virtualizing, mediating, orchestrating messaging substrate permeating the Enterprise,
providing uniform and mediated access anytime and anywhere throughout today’s global
Enterprise. That idea is so beautiful, it rivals My Little Pony. Sadly, it’s also
about as realistic. We tried regardless.
&lt;/p&gt;
&lt;p&gt;
As with many utopian ideas, before we can get to the pure ideal of an ESB, there’s
some less ideal and usually fairly ugly phase involved where non-conformant services
are made conformant. Until they are turned into WS-* services, any CICS transaction
and SAP BAPI is fronted with a translator and as that skinning renovation takes place,
there’s also some optimization around message flow, meaning messages get batched or
de-batched, enriched or reduced. In that phase, there was also learning of the value
and lure of the benefits of central control. SOA Governance is an interesting idea
to get customers drunk on. That ultimately led to cheating on the ‘B’. When you look
around and look at products proudly carrying the moniker ‘Enterprise Service Bus’
you will see hubs. In practice, the B in ESB is mostly just a lie. Some vendors sell
ESB servers, some even sell ESB appliances. If you need to walk to a central place
to talk to anyone, it’s a hub. Not a bus. 
&lt;/p&gt;
&lt;p&gt;
Yet, the bus does exist. The IP network is the bus. It turns out to suit us well on
the Internet. Mind that I’m explicitly talking about “IP network” and not “Web” as
I do believe that there are very many useful protocols beyond HTTP. The Web is obviously
the banner example for a successful implementation of services on the IP network that
does just fine without any form of centralized services other than the highly redundant
domain name system. 
&lt;/p&gt;
&lt;p&gt;
Centralized control over services does not scale in any dimension. Intentionally creating
a bottleneck through a centrally controlling committee of ESB machines, however far
scaled out, is not a winning proposition in a time where every potential or actual
customer carries a powerful computer in their pockets allowing to initiate ad-hoc
transactions at any time and from anywhere and where we see vehicles, machines and
devices increasingly spew out telemetry and accept remote control commands. Central
control and policy driven governance over all services in an Enterprise also kills
all agility and reduces the ability to adapt services to changing needs because governance
invariably implies process and certification. Five-year plan, anyone? 
&lt;/p&gt;
&lt;p&gt;
If the ESB architecture ideal weren’t a failure already, the competitive pressure
to adopt direct digital interaction with customers via Web and Apps, and therefore
scale up not to the scale of the enterprise, but to scale up to the scale of the enterprise’s
customer base will seal its collapse. 
&lt;/p&gt;
&lt;h3&gt;Service Orientation
&lt;/h3&gt;
&lt;p&gt;
While the ESB as a concept permeating the entire Enterprise is dead, the related notion
of Service Orientation is thriving even though the &lt;a href="http://msdn.microsoft.com/en-us/library/ff648318.aspx#SOATenets"&gt;four
tenets of SOA&lt;/a&gt; are rarely mentioned anymore. HTTP-based services on the Web embrace
explicit message passing. They mostly do so over the baseline application contract
and negotiated payloads that the HTTP specification provides for. In the case of SOAP
or XML-RPC, they are using abstractions on top that have their own application protocol
semantics. Services are clearly understood as units of management, deployment, and
versioning and that understanding is codified in most platform-as-a-service offerings. 
&lt;/p&gt;
&lt;p&gt;
That said, while explicit boundaries, autonomy, and contract sharing have been clearly
established, the notion of policy-driven compatibility – arguably a political addition
to the list to motivate WS-Policy as the time – has generally been replaced by something
even more powerful: Code. JavaScript code to be more precise. Instead of trying to
tell a generic client how to adapt to service settings by ways of giving it a complex
document explaining what switches to turn, clients now get code that turns the switches
outright. The successful alternative is to simply provide no choice. There’s one way
to gain access authorization for a service, period. The “policy” is in the docs. 
&lt;/p&gt;
&lt;p&gt;
The REST architecture model is service oriented – and I am not meaning to imply that
it is so because of any particular influence. The foundational principles were becoming
common sense around the time when these terms were coined and as the notion of broadly
interoperable programmable services started to gain traction in the late 1990s – the
subsequent grand dissent that arose was around whether pure HTTP was sufficient to
build these services, or whether the ambitious multi-protocol abstraction for WS-*
would be needed. I think it’s fairly easy to declare the winner there. 
&lt;/p&gt;
&lt;h3&gt;Federated Autonomous Services
&lt;/h3&gt;
&lt;p&gt;
&lt;a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Utopia-ESB_87DD/image_2.png"&gt;&lt;img title=image style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; FLOAT: right; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" border=0 alt=image align=right src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Utopia-ESB_87DD/image_thumb.png" width=240 height=213&gt;&lt;/a&gt;Windows
Azure, to name a system that would surely be one to fit the kind of solution complexity
that ESBs were aimed at, is a very large distributed system with a significant number
of independent multi-tenant services and deployments that are spread across many data
centers. In addition to the publicly exposed capabilities, there are quite a number
of “invisible” services for provisioning, usage tracking and analysis, billing, diagnostics,
deployment, and other purposes.&amp;nbsp; Some components of these internal services integrate
with external providers. Windows Azure doesn’t use an ESB. Windows Azure is a federation
of autonomous services.
&lt;/p&gt;
&lt;p&gt;
The basic shape of each of these services is effectively identical and that’s not
owing, at least not to my knowledge, to any central architectural directive even though
the services that shipped after the initial wave certainly took a good look at the
patterns that emerged. Practically all services have a gateway whose purpose it is
to handle and dispatch and sometimes preprocess incoming network requests or sessions
and a backend that ultimately fulfills the requests. The services interact through
public IP space, meaning that if Service Bus wants to talk to its SQL Database backend
it is using a public IP address and not some private IP. The Internet is the bus.
The backend and its structure is entirely a private implementation matter.&amp;nbsp; It
could be a single role or many roles. 
&lt;/p&gt;
&lt;p&gt;
Any gateway’s job is to provide network request management, which includes establishing
and maintaining sessions, session security and authorization, API versioning where
multiple variants of the same API are often provided in parallel, usage tracking,
defense mechanisms, and diagnostics for its areas of responsibility. This functionality
is specific and inherent to the service. And it’s not all HTTP. SQL database has a
gateway that speaks the Tabular Data Stream protocol (TDS) over TCP, for instance,
and Service Bus has a gateway that speaks AMQP and the binary proprietary Relay and
Messaging protocols.
&lt;/p&gt;
&lt;p&gt;
Governance and diagnostics doesn’t work by putting a man in the middle and watching
the traffic coming by, which is akin to trying the tell whether a business is healthy
by counting the trucks going to their warehouse. Instead we are integrating the data
feeds that come out of the respective services and are generated fully knowing the
internal state, and concentrate these data streams, like the billing stream, in yet
other services that are also autonomous and have their own gateways. All these services
interact and integrate even though they’re built by a composite team far exceeding
the scale of most Enterprise’s largest projects, and while teams run on separate schedules
where deployments into the overall system happen multiple times daily. It works because
each service owns its gateway, is explicit about its versioning strategy, and has
a very clear mandate to honor published contracts, which includes explicit regression
testing. It would be unfathomable to maintain a system of this scale through a centrally
governed switchboard service like an ESB.
&lt;/p&gt;
&lt;p&gt;
Well, where does that leave “ESB technologies” like BizTalk Server? The answer is
simply that they’re being used for what they’re commonly used for in practice. As
a gateway technology. Once a service in such a federation would have to adhere to
a particular industry standard for commerce, for instance if it would have to understand
EDIFACT or X.12 messages sent to it, the Gateway would employ an appropriate and proven
implementation and thus likely rely on BizTalk if implemented on the Microsoft stack.
If a service would have to speak to an external service for which it would have to
build EDI exchanges, it would likely be very cost effective to also use BizTalk as
the appropriate tool for that outbound integration. Likewise, if data would have to
be extracted from backend-internal message traffic for tracking purposes and BizTalk’s
BAM capabilities would be a fit, it might be a reasonable component to use for that.
If there’s a long running process around exchanging electronic documents, BizTalk
Orchestration might be appropriate, if there’s a document exchange involving humans
then SharePoint and/or Workflow would be a good candidate from the toolset. 
&lt;/p&gt;
&lt;p&gt;
For most services, the key gateway technology of choice is HTTP using frameworks like
ASP.NET, Web API, probably paired with IIS features like application request routing
and the gateway is largely stateless.
&lt;/p&gt;
&lt;p&gt;
In this context, &lt;em&gt;Windows Azure Service Bus&lt;/em&gt; is, in fact, a technology choice
to implement application gateways. A Service Bus namespace thus forms a message bus
for “a service” and not for “all services”. It’s as scoped to a service or a set of
related services as an IIS site is usually scoped to one or a few related services.
The Relay is a way to place a gateway into the cloud for services where the backend
resides outside of the cloud environment and it also allows for multiple systems,
e.g. branch systems, to be federated into a single gateway to be addressed from other
systems and thus form a gateway of gateways. The messaging capabilities with Queues
and Pub/Sub Topics provide a way for inbound traffic to be authorized and queued up
on behalf of the service, with Service Bus acting as the mediator and first line of
defense and where a service will never get a message from the outside world unless
it explicitly fetches it from Service Bus. The service can’t be overstressed and it
can’t be accessed except through sending it a message. 
&lt;/p&gt;
&lt;p&gt;
The next logical step on that journey is to provide federation capabilities with reliable
handoff of message between services, meaning that you can safely enqueue a message
within a service and then have Service Bus replicate that message (or one copy in
the case of pub/sub) over to another service’s Gateway – across namespaces and across
datacenters or your own sites, and using the open AMQP protocol. You can do that today
with a few lines of code, but this will become inherent to the system later this year. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=4718bf97-cc2e-46ba-854a-f4a1d93fb2a9" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,4718bf97-cc2e-46ba-854a-f4a1d93fb2a9.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Azure</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=1e55de13-92c3-46ed-b01c-dcda6cc5ecf6</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,1e55de13-92c3-46ed-b01c-dcda6cc5ecf6.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,1e55de13-92c3-46ed-b01c-dcda6cc5ecf6.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=1e55de13-92c3-46ed-b01c-dcda6cc5ecf6</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Today has been a lively day in some parts of the Twitterverse debating the Saga pattern.
As it stands, there are a few frameworks for .NET out there that use the term "Saga"
for some framework implementation of a state machine or workflow. Trouble is,
that's not what a Saga is. A Saga is a failure management pattern. 
</p>
        <p>
Sagas come out of the realization that particularly long-lived transactions (originally
even just inside databases), but also far distributed transactions across location
and/or trust boundaries can't eaily be handled using the classic ACID model with 2-Phase
commit and holding locks for the duration of the work. Instead, a Saga splits work
into individual transactions whose effects can be, somehow, reversed after work has
been performed and commited.
</p>
        <p align="left">
          <a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Sagas_1273E/image_4.png">
            <img title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; FLOAT: none; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN-LEFT: auto; DISPLAY: block; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; MARGIN-RIGHT: auto" border="0" alt="image" src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Sagas_1273E/image_thumb_1.png" width="672" height="296" />
          </a>
        </p>
        <p>
The picture shows a simple Saga. If you book a travel itinerary, you want a car and
a hotel and a flight. If you can't get all of them, it's probably not worth going.
It's also very certain that you can't enlist all of these providers into a distributed
ACID transaction. Instead, you'll have an activity for booking rental cars that knows
both how to perform a reservation and also how to cancel it - and one for a hotel
and one for flights. 
</p>
        <p>
The activities are grouped in a composite job (routing slip) that's handed along the
activity chain. If you want, you can sign/encrypt the routing slip items so that they
can only be understood and manipulated by the intended receiver. When an activity
completes, it adds a record of the completion to the routing slip along with information
on where its compensating operation can be reached (e.g. via a Queue). When an activity
fails, it cleans up locally and then sends the routing slip backwards to the last
completed activity's compensation address to unwind the transaction outcome.
</p>
        <p>
If you're a bit familiar with travel, you'll also notice that I've organized the steps
by risk. Reserving a rental car almost always succeeds if you book in advance, because
the rental car company can move more cars on-site of there is high demand. Reserving
a hotel is slightly more risky, but you can commonly back out of a reservation without
penalty until 24h before the stay. Airfare often comes with a refund restriction,
so you'll want to do that last.
</p>
        <p>
I created a <a href="https://gist.github.com/3562597">Gist on Github that you can
run as a console application</a>. It illustrates this model in code. Mind that it
is a mockup and not a framework. I wrote this in less than 90 minutes, so don't expect
to reuse this.
</p>
        <p>
The main program sets up an examplary routing slip (all the classes are in the one
file) and creates three completely independent "processes" (activity hosts) that are
each responsible for handling a particular kind of work. The "processes" are linked
by a "network" and each kind of activity has an address for forward progress work
and one of compensation work. The network resolution is simulated by 'Send".
</p>
        <p>
        </p>
        <div class="csharpcode">
          <pre>
            <span class="lnum"> 1: </span>
            <span class="kwrd">static</span> ActivityHost[]
processes;</pre>
          <pre>
            <span class="lnum"> 2: </span> </pre>
          <pre>
            <span class="lnum"> 3: </span>
            <span class="kwrd">static</span>
            <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[]
args)</pre>
          <pre>
            <span class="lnum"> 4: </span>{</pre>
          <pre>
            <span class="lnum"> 5: </span> var routingSlip = <span class="kwrd">new</span> RoutingSlip(<span class="kwrd">new</span> WorkItem[]</pre>
          <pre>
            <span class="lnum"> 6: </span> {</pre>
          <pre>
            <span class="lnum"> 7: </span>
            <span class="kwrd">new</span> WorkItem&lt;ReserveCarActivity&gt;(<span class="kwrd">new</span> WorkItemArguments{{<span class="str">"vehicleType"</span>, <span class="str">"Compact"</span>}}),</pre>
          <pre>
            <span class="lnum"> 8: </span>
            <span class="kwrd">new</span> WorkItem&lt;ReserveHotelActivity&gt;(<span class="kwrd">new</span> WorkItemArguments{{<span class="str">"roomType"</span>, <span class="str">"Suite"</span>}}),</pre>
          <pre>
            <span class="lnum"> 9: </span>
            <span class="kwrd">new</span> WorkItem&lt;ReserveFlightActivity&gt;(<span class="kwrd">new</span> WorkItemArguments{{<span class="str">"destination"</span>, <span class="str">"DUS"</span>}})</pre>
          <pre>
            <span class="lnum"> 10: </span> });</pre>
          <pre>
            <span class="lnum"> 11: </span> </pre>
          <pre>
            <span class="lnum"> 12: </span> </pre>
          <pre>
            <span class="lnum"> 13: </span>
            <span class="rem">// imagine these being completely
separate processes with queues between them</span>
          </pre>
          <pre>
            <span class="lnum"> 14: </span> processes = <span class="kwrd">new</span> ActivityHost[]</pre>
          <pre>
            <span class="lnum"> 15: </span> {</pre>
          <pre>
            <span class="lnum"> 16: </span>
            <span class="kwrd">new</span> ActivityHost&lt;ReserveCarActivity&gt;(Send),</pre>
          <pre>
            <span class="lnum"> 17: </span>
            <span class="kwrd">new</span> ActivityHost&lt;ReserveHotelActivity&gt;(Send),</pre>
          <pre>
            <span class="lnum"> 18: </span>
            <span class="kwrd">new</span> ActivityHost&lt;ReserveFlightActivity&gt;(Send)</pre>
          <pre>
            <span class="lnum"> 19: </span> };</pre>
          <pre>
            <span class="lnum"> 20: </span> </pre>
          <pre>
            <span class="lnum"> 21: </span>
            <span class="rem">// hand off to the first address</span>
          </pre>
          <pre>
            <span class="lnum"> 22: </span> Send(routingSlip.ProgressUri, routingSlip);</pre>
          <pre>
            <span class="lnum"> 23: </span>}</pre>
          <pre>
            <span class="lnum"> 24: </span> </pre>
          <pre>
            <span class="lnum"> 25: </span>
            <span class="kwrd">static</span>
            <span class="kwrd">void</span> Send(Uri
uri, RoutingSlip routingSlip)</pre>
          <pre>
            <span class="lnum"> 26: </span>{</pre>
          <pre>
            <span class="lnum"> 27: </span>
            <span class="rem">// this is effectively the
network dispatch</span>
          </pre>
          <pre>
            <span class="lnum"> 28: </span>
            <span class="kwrd">foreach</span> (var process <span class="kwrd">in</span> processes)</pre>
          <pre>
            <span class="lnum"> 29: </span> {</pre>
          <pre>
            <span class="lnum"> 30: </span>
            <span class="kwrd">if</span> (process.AcceptMessage(uri,
routingSlip))</pre>
          <pre>
            <span class="lnum"> 31: </span> {</pre>
          <pre>
            <span class="lnum"> 32: </span>
            <span class="kwrd">break</span>;</pre>
          <pre>
            <span class="lnum"> 33: </span> }</pre>
          <pre>
            <span class="lnum"> 34: </span> }</pre>
          <pre>
            <span class="lnum"> 35: </span>}</pre>
        </div>
        <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
        <p>
The activities each implement a reservation step and an undo step. Here's the one
for cars:
</p>
        <div class="csharpcode">
          <pre>
            <span class="lnum"> 1: </span>
            <span class="kwrd">class</span> ReserveCarActivity
: Activity</pre>
          <pre>
            <span class="lnum"> 2: </span>{</pre>
          <pre>
            <span class="lnum"> 3: </span>
            <span class="kwrd">static</span> Random rnd = <span class="kwrd">new</span> Random(2);</pre>
          <pre>
            <span class="lnum"> 4: </span> </pre>
          <pre>
            <span class="lnum"> 5: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">override</span> WorkLog
DoWork(WorkItem workItem)</pre>
          <pre>
            <span class="lnum"> 6: </span> {</pre>
          <pre>
            <span class="lnum"> 7: </span> Console.WriteLine(<span class="str">"Reserving
car"</span>);</pre>
          <pre>
            <span class="lnum"> 8: </span> var car = workItem.Arguments[<span class="str">"vehicleType"</span>];</pre>
          <pre>
            <span class="lnum"> 9: </span> var reservationId = rnd.Next(100000);</pre>
          <pre>
            <span class="lnum"> 10: </span> Console.WriteLine(<span class="str">"Reserved
car {0}"</span>, reservationId);</pre>
          <pre>
            <span class="lnum"> 11: </span>
            <span class="kwrd">return</span>
            <span class="kwrd">new</span> WorkLog(<span class="kwrd">this</span>, <span class="kwrd">new</span> WorkResult
{ { <span class="str">"reservationId"</span>, reservationId } });</pre>
          <pre>
            <span class="lnum"> 12: </span> }</pre>
          <pre>
            <span class="lnum"> 13: </span> </pre>
          <pre>
            <span class="lnum"> 14: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">override</span>
            <span class="kwrd">bool</span> Compensate(WorkLog
item, RoutingSlip routingSlip)</pre>
          <pre>
            <span class="lnum"> 15: </span> {</pre>
          <pre>
            <span class="lnum"> 16: </span> var reservationId = item.Result[<span class="str">"reservationId"</span>];</pre>
          <pre>
            <span class="lnum"> 17: </span> Console.WriteLine(<span class="str">"Cancelled
car {0}"</span>, reservationId);</pre>
          <pre>
            <span class="lnum"> 18: </span>
            <span class="kwrd">return</span>
            <span class="kwrd">true</span>;</pre>
          <pre>
            <span class="lnum"> 19: </span> }</pre>
          <pre>
            <span class="lnum"> 20: </span> </pre>
          <pre>
            <span class="lnum"> 21: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">override</span> Uri
WorkItemQueueAddress</pre>
          <pre>
            <span class="lnum"> 22: </span> {</pre>
          <pre>
            <span class="lnum"> 23: </span> get { <span class="kwrd">return</span><span class="kwrd">new</span> Uri(<span class="str">"sb://./carReservations"</span>);
}</pre>
          <pre>
            <span class="lnum"> 24: </span> }</pre>
          <pre>
            <span class="lnum"> 25: </span> </pre>
          <pre>
            <span class="lnum"> 26: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">override</span> Uri
CompensationQueueAddress</pre>
          <pre>
            <span class="lnum"> 27: </span> {</pre>
          <pre>
            <span class="lnum"> 28: </span> get { <span class="kwrd">return</span><span class="kwrd">new</span> Uri(<span class="str">"sb://./carCancellactions"</span>);
}</pre>
          <pre>
            <span class="lnum"> 29: </span> }</pre>
          <pre>
            <span class="lnum"> 30: </span>}</pre>
        </div>
        <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
        <p>
The chaining happens solely through the routing slip. The routing slip is "serializable"
(it's not, pretend that it is) and it's the only piece of information that flows between
the collaborating activities. There is no central coordination. All work is local
on the nodes and once a node is done, it either hands the routing slip forward (on
success) or backward (on failure). For forward progress data, the routing slip has
a queue and for backwards items it maintains a stack. The routing slip also handles
resolving and invoking whatever the "next" thing to call is on the way forward and
backward.
</p>
        <div class="csharpcode">
          <pre>
            <span class="lnum"> 1: </span>
            <span class="kwrd">class</span> RoutingSlip</pre>
          <pre>
            <span class="lnum"> 2: </span>{</pre>
          <pre>
            <span class="lnum"> 3: </span>
            <span class="kwrd">readonly</span> Stack&lt;WorkLog&gt;
completedWorkLogs = <span class="kwrd">new</span> Stack&lt;WorkLog&gt;();</pre>
          <pre>
            <span class="lnum"> 4: </span>
            <span class="kwrd">readonly</span> Queue&lt;WorkItem&gt;
nextWorkItem = <span class="kwrd">new</span> Queue&lt;WorkItem&gt;();</pre>
          <pre>
            <span class="lnum"> 5: </span> </pre>
          <pre>
            <span class="lnum"> 6: </span>
            <span class="kwrd">public</span> RoutingSlip()</pre>
          <pre>
            <span class="lnum"> 7: </span> {</pre>
          <pre>
            <span class="lnum"> 8: </span> }</pre>
          <pre>
            <span class="lnum"> 9: </span> </pre>
          <pre>
            <span class="lnum"> 10: </span>
            <span class="kwrd">public</span> RoutingSlip(IEnumerable&lt;WorkItem&gt;
workItems)</pre>
          <pre>
            <span class="lnum"> 11: </span> {</pre>
          <pre>
            <span class="lnum"> 12: </span>
            <span class="kwrd">foreach</span> (var workItem <span class="kwrd">in</span> workItems)</pre>
          <pre>
            <span class="lnum"> 13: </span> {</pre>
          <pre>
            <span class="lnum"> 14: </span>
            <span class="kwrd">this</span>.nextWorkItem.Enqueue(workItem);</pre>
          <pre>
            <span class="lnum"> 15: </span> }</pre>
          <pre>
            <span class="lnum"> 16: </span> }</pre>
          <pre>
            <span class="lnum"> 17: </span> </pre>
          <pre>
            <span class="lnum"> 18: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">bool</span> IsCompleted</pre>
          <pre>
            <span class="lnum"> 19: </span> {</pre>
          <pre>
            <span class="lnum"> 20: </span> get { <span class="kwrd">return</span><span class="kwrd">this</span>.nextWorkItem.Count
== 0; }</pre>
          <pre>
            <span class="lnum"> 21: </span> }</pre>
          <pre>
            <span class="lnum"> 22: </span> </pre>
          <pre>
            <span class="lnum"> 23: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">bool</span> IsInProgress</pre>
          <pre>
            <span class="lnum"> 24: </span> {</pre>
          <pre>
            <span class="lnum"> 25: </span> get { <span class="kwrd">return</span><span class="kwrd">this</span>.completedWorkLogs.Count
&gt; 0; }</pre>
          <pre>
            <span class="lnum"> 26: </span> }</pre>
          <pre>
            <span class="lnum"> 27: </span> </pre>
          <pre>
            <span class="lnum"> 28: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">bool</span> ProcessNext()</pre>
          <pre>
            <span class="lnum"> 29: </span> {</pre>
          <pre>
            <span class="lnum"> 30: </span>
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.IsCompleted)</pre>
          <pre>
            <span class="lnum"> 31: </span> {</pre>
          <pre>
            <span class="lnum"> 32: </span>
            <span class="kwrd">throw</span>
            <span class="kwrd">new</span> InvalidOperationException();</pre>
          <pre>
            <span class="lnum"> 33: </span> }</pre>
          <pre>
            <span class="lnum"> 34: </span> </pre>
          <pre>
            <span class="lnum"> 35: </span> var currentItem = <span class="kwrd">this</span>.nextWorkItem.Dequeue();</pre>
          <pre>
            <span class="lnum"> 36: </span> var activity = (Activity)Activator.CreateInstance(currentItem.ActivityType);</pre>
          <pre>
            <span class="lnum"> 37: </span>
            <span class="kwrd">try</span>
          </pre>
          <pre>
            <span class="lnum"> 38: </span> {</pre>
          <pre>
            <span class="lnum"> 39: </span> var result = activity.DoWork(currentItem);</pre>
          <pre>
            <span class="lnum"> 40: </span>
            <span class="kwrd">if</span> (result != <span class="kwrd">null</span>)</pre>
          <pre>
            <span class="lnum"> 41: </span> {</pre>
          <pre>
            <span class="lnum"> 42: </span>
            <span class="kwrd">this</span>.completedWorkLogs.Push(result);</pre>
          <pre>
            <span class="lnum"> 43: </span>
            <span class="kwrd">return</span>
            <span class="kwrd">true</span>;</pre>
          <pre>
            <span class="lnum"> 44: </span> }</pre>
          <pre>
            <span class="lnum"> 45: </span> }</pre>
          <pre>
            <span class="lnum"> 46: </span>
            <span class="kwrd">catch</span> (Exception e)</pre>
          <pre>
            <span class="lnum"> 47: </span> {</pre>
          <pre>
            <span class="lnum"> 48: </span> Console.WriteLine(<span class="str">"Exception
{0}"</span>, e.Message);</pre>
          <pre>
            <span class="lnum"> 49: </span> }</pre>
          <pre>
            <span class="lnum"> 50: </span>
            <span class="kwrd">return</span>
            <span class="kwrd">false</span>;</pre>
          <pre>
            <span class="lnum"> 51: </span> }</pre>
          <pre>
            <span class="lnum"> 52: </span> </pre>
          <pre>
            <span class="lnum"> 53: </span>
            <span class="kwrd">public</span> Uri ProgressUri</pre>
          <pre>
            <span class="lnum"> 54: </span> {</pre>
          <pre>
            <span class="lnum"> 55: </span> get</pre>
          <pre>
            <span class="lnum"> 56: </span> {</pre>
          <pre>
            <span class="lnum"> 57: </span>
            <span class="kwrd">if</span> (IsCompleted)</pre>
          <pre>
            <span class="lnum"> 58: </span> {</pre>
          <pre>
            <span class="lnum"> 59: </span>
            <span class="kwrd">return</span>
            <span class="kwrd">null</span>;</pre>
          <pre>
            <span class="lnum"> 60: </span> }</pre>
          <pre>
            <span class="lnum"> 61: </span>
            <span class="kwrd">else</span>
          </pre>
          <pre>
            <span class="lnum"> 62: </span> {</pre>
          <pre>
            <span class="lnum"> 63: </span>
            <span class="kwrd">return</span>
          </pre>
          <pre>
            <span class="lnum"> 64: </span> ((Activity)Activator.CreateInstance(<span class="kwrd">this</span>.nextWorkItem.Peek().ActivityType)).</pre>
          <pre>
            <span class="lnum"> 65: </span> WorkItemQueueAddress;</pre>
          <pre>
            <span class="lnum"> 66: </span> }</pre>
          <pre>
            <span class="lnum"> 67: </span> }</pre>
          <pre>
            <span class="lnum"> 68: </span> }</pre>
          <pre>
            <span class="lnum"> 69: </span> </pre>
          <pre>
            <span class="lnum"> 70: </span>
            <span class="kwrd">public</span> Uri CompensationUri</pre>
          <pre>
            <span class="lnum"> 71: </span> {</pre>
          <pre>
            <span class="lnum"> 72: </span> get</pre>
          <pre>
            <span class="lnum"> 73: </span> {</pre>
          <pre>
            <span class="lnum"> 74: </span>
            <span class="kwrd">if</span> (!IsInProgress)</pre>
          <pre>
            <span class="lnum"> 75: </span> {</pre>
          <pre>
            <span class="lnum"> 76: </span>
            <span class="kwrd">return</span>
            <span class="kwrd">null</span>;</pre>
          <pre>
            <span class="lnum"> 77: </span> }</pre>
          <pre>
            <span class="lnum"> 78: </span>
            <span class="kwrd">else</span>
          </pre>
          <pre>
            <span class="lnum"> 79: </span> {</pre>
          <pre>
            <span class="lnum"> 80: </span>
            <span class="kwrd">return</span>
          </pre>
          <pre>
            <span class="lnum"> 81: </span> ((Activity)Activator.CreateInstance(<span class="kwrd">this</span>.completedWorkLogs.Peek().ActivityType)).</pre>
          <pre>
            <span class="lnum"> 82: </span> CompensationQueueAddress;</pre>
          <pre>
            <span class="lnum"> 83: </span> }</pre>
          <pre>
            <span class="lnum"> 84: </span> }</pre>
          <pre>
            <span class="lnum"> 85: </span> }</pre>
          <pre>
            <span class="lnum"> 86: </span> </pre>
          <pre>
            <span class="lnum"> 87: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">bool</span> UndoLast()</pre>
          <pre>
            <span class="lnum"> 88: </span> {</pre>
          <pre>
            <span class="lnum"> 89: </span>
            <span class="kwrd">if</span> (!<span class="kwrd">this</span>.IsInProgress)</pre>
          <pre>
            <span class="lnum"> 90: </span> {</pre>
          <pre>
            <span class="lnum"> 91: </span>
            <span class="kwrd">throw</span>
            <span class="kwrd">new</span> InvalidOperationException();</pre>
          <pre>
            <span class="lnum"> 92: </span> }</pre>
          <pre>
            <span class="lnum"> 93: </span> </pre>
          <pre>
            <span class="lnum"> 94: </span> var currentItem = <span class="kwrd">this</span>.completedWorkLogs.Pop();</pre>
          <pre>
            <span class="lnum"> 95: </span> var activity = (Activity)Activator.CreateInstance(currentItem.ActivityType);</pre>
          <pre>
            <span class="lnum"> 96: </span>
            <span class="kwrd">try</span>
          </pre>
          <pre>
            <span class="lnum"> 97: </span> {</pre>
          <pre>
            <span class="lnum"> 98: </span>
            <span class="kwrd">return</span> activity.Compensate(currentItem, <span class="kwrd">this</span>);</pre>
          <pre>
            <span class="lnum"> 99: </span> }</pre>
          <pre>
            <span class="lnum"> 100: </span>
            <span class="kwrd">catch</span> (Exception e)</pre>
          <pre>
            <span class="lnum"> 101: </span> {</pre>
          <pre>
            <span class="lnum"> 102: </span> Console.WriteLine(<span class="str">"Exception
{0}"</span>, e.Message);</pre>
          <pre>
            <span class="lnum"> 103: </span>
            <span class="kwrd">throw</span>;</pre>
          <pre>
            <span class="lnum"> 104: </span> }</pre>
          <pre>
            <span class="lnum"> 105: </span> </pre>
          <pre>
            <span class="lnum"> 106: </span> }</pre>
          <pre>
            <span class="lnum"> 107: </span>}</pre>
        </div>
        <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
        <p>
The local work  and making the decisions is encapsulated in the ActivityHost,
which calls ProcessNext() on the routing slip to resolve the next activity and call
its DoWork() function on the way forward or will resolve the last executed activity
on the way back and invoke its Compensate() function. Again, there's nothing centralized
here; all that work hinges on the routing slip and the three activities and their
execution is completely disjoint.
</p>
        <div class="csharpcode">
          <pre>
            <span class="lnum"> 1: </span>
            <span class="kwrd">abstract</span>
            <span class="kwrd">class</span> ActivityHost</pre>
          <pre>
            <span class="lnum"> 2: </span>{</pre>
          <pre>
            <span class="lnum"> 3: </span> Action&lt;Uri, RoutingSlip&gt; send;</pre>
          <pre>
            <span class="lnum"> 4: </span> </pre>
          <pre>
            <span class="lnum"> 5: </span>
            <span class="kwrd">public</span> ActivityHost(Action&lt;Uri,
RoutingSlip&gt; send)</pre>
          <pre>
            <span class="lnum"> 6: </span> {</pre>
          <pre>
            <span class="lnum"> 7: </span>
            <span class="kwrd">this</span>.send = send;</pre>
          <pre>
            <span class="lnum"> 8: </span> }</pre>
          <pre>
            <span class="lnum"> 9: </span> </pre>
          <pre>
            <span class="lnum"> 10: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">void</span> ProcessForwardMessage(RoutingSlip
routingSlip)</pre>
          <pre>
            <span class="lnum"> 11: </span> {</pre>
          <pre>
            <span class="lnum"> 12: </span>
            <span class="kwrd">if</span> (!routingSlip.IsCompleted)</pre>
          <pre>
            <span class="lnum"> 13: </span> {</pre>
          <pre>
            <span class="lnum"> 14: </span>
            <span class="rem">// if the current step is successful,
proceed</span>
          </pre>
          <pre>
            <span class="lnum"> 15: </span>
            <span class="rem">// otherwise go to the Unwind
path</span>
          </pre>
          <pre>
            <span class="lnum"> 16: </span>
            <span class="kwrd">if</span> (routingSlip.ProcessNext())</pre>
          <pre>
            <span class="lnum"> 17: </span> {</pre>
          <pre>
            <span class="lnum"> 18: </span>
            <span class="rem">// recursion stands for passing
context via message</span>
          </pre>
          <pre>
            <span class="lnum"> 19: </span>
            <span class="rem">// the routing slip can be
fully serialized and passed</span>
          </pre>
          <pre>
            <span class="lnum"> 20: </span>
            <span class="rem">// between systems. </span>
          </pre>
          <pre>
            <span class="lnum"> 21: </span>
            <span class="kwrd">this</span>.send(routingSlip.ProgressUri,
routingSlip);</pre>
          <pre>
            <span class="lnum"> 22: </span> }</pre>
          <pre>
            <span class="lnum"> 23: </span>
            <span class="kwrd">else</span>
          </pre>
          <pre>
            <span class="lnum"> 24: </span> {</pre>
          <pre>
            <span class="lnum"> 25: </span>
            <span class="rem">// pass message to unwind message
route</span>
          </pre>
          <pre>
            <span class="lnum"> 26: </span>
            <span class="kwrd">this</span>.send(routingSlip.CompensationUri,
routingSlip);</pre>
          <pre>
            <span class="lnum"> 27: </span> }</pre>
          <pre>
            <span class="lnum"> 28: </span> }</pre>
          <pre>
            <span class="lnum"> 29: </span> }</pre>
          <pre>
            <span class="lnum"> 30: </span> </pre>
          <pre>
            <span class="lnum"> 31: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">void</span> ProcessBackwardMessage(RoutingSlip
routingSlip)</pre>
          <pre>
            <span class="lnum"> 32: </span> {</pre>
          <pre>
            <span class="lnum"> 33: </span>
            <span class="kwrd">if</span> (routingSlip.IsInProgress)</pre>
          <pre>
            <span class="lnum"> 34: </span> {</pre>
          <pre>
            <span class="lnum"> 35: </span>
            <span class="rem">// UndoLast can put new work
on the routing slip</span>
          </pre>
          <pre>
            <span class="lnum"> 36: </span>
            <span class="rem">// and return false to go back
on the forward </span>
          </pre>
          <pre>
            <span class="lnum"> 37: </span>
            <span class="rem">// path</span>
          </pre>
          <pre>
            <span class="lnum"> 38: </span>
            <span class="kwrd">if</span> (routingSlip.UndoLast())</pre>
          <pre>
            <span class="lnum"> 39: </span> {</pre>
          <pre>
            <span class="lnum"> 40: </span>
            <span class="rem">// recursion stands for passing
context via message</span>
          </pre>
          <pre>
            <span class="lnum"> 41: </span>
            <span class="rem">// the routing slip can be
fully serialized and passed</span>
          </pre>
          <pre>
            <span class="lnum"> 42: </span>
            <span class="rem">// between systems </span>
          </pre>
          <pre>
            <span class="lnum"> 43: </span>
            <span class="kwrd">this</span>.send(routingSlip.CompensationUri,
routingSlip);</pre>
          <pre>
            <span class="lnum"> 44: </span> }</pre>
          <pre>
            <span class="lnum"> 45: </span>
            <span class="kwrd">else</span>
          </pre>
          <pre>
            <span class="lnum"> 46: </span> {</pre>
          <pre>
            <span class="lnum"> 47: </span>
            <span class="kwrd">this</span>.send(routingSlip.ProgressUri,
routingSlip);</pre>
          <pre>
            <span class="lnum"> 48: </span> }</pre>
          <pre>
            <span class="lnum"> 49: </span> }</pre>
          <pre>
            <span class="lnum"> 50: </span> }</pre>
          <pre>
            <span class="lnum"> 51: </span> </pre>
          <pre>
            <span class="lnum"> 52: </span>
            <span class="kwrd">public</span>
            <span class="kwrd">abstract</span>
            <span class="kwrd">bool</span> AcceptMessage(Uri
uri, RoutingSlip routingSlip);</pre>
          <pre>
            <span class="lnum"> 53: </span>}</pre>
        </div>
        <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
        <p>
 
</p>
        <p>
That's a Saga.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1e55de13-92c3-46ed-b01c-dcda6cc5ecf6" />
      </body>
      <title>Sagas</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,1e55de13-92c3-46ed-b01c-dcda6cc5ecf6.aspx</guid>
      <link>http://vasters.com/clemensv/2012/09/01/Sagas.aspx</link>
      <pubDate>Sat, 01 Sep 2012 04:49:00 GMT</pubDate>
      <description>&lt;p&gt;
Today has been a lively day in some parts of the Twitterverse debating the Saga pattern.
As it stands, there are a few frameworks for .NET out there that use the term "Saga"
for&amp;nbsp;some framework implementation of a state machine or workflow. Trouble is,
that's not what a Saga is. A Saga is a failure management pattern. 
&lt;/p&gt;
&lt;p&gt;
Sagas come out of the realization that particularly long-lived transactions (originally
even just inside databases), but also far distributed transactions across location
and/or trust boundaries can't eaily be handled using the classic ACID model with 2-Phase
commit and holding locks for the duration of the work. Instead, a Saga splits work
into individual transactions whose effects can be, somehow, reversed after work has
been performed and commited.
&lt;/p&gt;
&lt;p align=left&gt;
&lt;a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Sagas_1273E/image_4.png"&gt;&lt;img title=image style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; FLOAT: none; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN-LEFT: auto; DISPLAY: block; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; MARGIN-RIGHT: auto" border=0 alt=image src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/Sagas_1273E/image_thumb_1.png" width=672 height=296&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
The picture shows a simple Saga. If you book a travel itinerary, you want a car and
a hotel and a flight. If you can't get all of them, it's probably not worth going.
It's also very certain that you can't enlist all of these providers into a distributed
ACID transaction. Instead, you'll have an activity for booking rental cars that knows
both how to perform a reservation and also how to cancel it - and one for a hotel
and one for flights. 
&lt;/p&gt;
&lt;p&gt;
The activities are grouped in a composite job (routing slip) that's handed along the
activity chain. If you want, you can sign/encrypt the routing slip items so that they
can only be understood and manipulated by the intended receiver. When an activity
completes, it adds a record of the completion to the routing slip along with information
on where its compensating operation can be reached (e.g. via a Queue). When an activity
fails, it cleans up locally and then sends the routing slip backwards to the last
completed activity's compensation address to unwind the transaction outcome.
&lt;/p&gt;
&lt;p&gt;
If you're a bit familiar with travel, you'll also notice that I've organized the steps
by risk. Reserving a rental car almost always succeeds if you book in advance, because
the rental car company can move more cars on-site of there is high demand. Reserving
a hotel is slightly more risky, but you can commonly back out of a reservation without
penalty until 24h before the stay. Airfare often comes with a refund restriction,
so you'll want to do that last.
&lt;/p&gt;
&lt;p&gt;
I created a &lt;a href="https://gist.github.com/3562597"&gt;Gist on Github that you can
run as a console application&lt;/a&gt;. It illustrates this model in code. Mind that it
is a mockup and not a framework. I wrote this in less than 90 minutes, so don't expect
to reuse this.
&lt;/p&gt;
&lt;p&gt;
The main program sets up an examplary routing slip (all the classes are in the one
file) and creates three completely independent "processes" (activity hosts) that are
each responsible for handling a particular kind of work. The "processes" are linked
by a "network" and each kind of activity has an address for forward progress work
and one of compensation work. The network resolution is simulated by 'Send".
&lt;/p&gt;
&lt;p&gt;
&gt;
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre&gt;&lt;span class=lnum&gt; 1: &lt;/span&gt;&lt;span class=kwrd&gt;static&lt;/span&gt; ActivityHost[]
processes;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 2: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 3: &lt;/span&gt;&lt;span class=kwrd&gt;static&lt;/span&gt; &lt;span class=kwrd&gt;void&lt;/span&gt; Main(&lt;span class=kwrd&gt;string&lt;/span&gt;[]
args)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 4: &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 5: &lt;/span&gt; var routingSlip = &lt;span class=kwrd&gt;new&lt;/span&gt; RoutingSlip(&lt;span class=kwrd&gt;new&lt;/span&gt; WorkItem[]&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 6: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 7: &lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; WorkItem&amp;lt;ReserveCarActivity&amp;gt;(&lt;span class=kwrd&gt;new&lt;/span&gt; WorkItemArguments{{&lt;span class=str&gt;"vehicleType"&lt;/span&gt;, &lt;span class=str&gt;"Compact"&lt;/span&gt;}}),&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 8: &lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; WorkItem&amp;lt;ReserveHotelActivity&amp;gt;(&lt;span class=kwrd&gt;new&lt;/span&gt; WorkItemArguments{{&lt;span class=str&gt;"roomType"&lt;/span&gt;, &lt;span class=str&gt;"Suite"&lt;/span&gt;}}),&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 9: &lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; WorkItem&amp;lt;ReserveFlightActivity&amp;gt;(&lt;span class=kwrd&gt;new&lt;/span&gt; WorkItemArguments{{&lt;span class=str&gt;"destination"&lt;/span&gt;, &lt;span class=str&gt;"DUS"&lt;/span&gt;}})&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 10: &lt;/span&gt; });&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 11: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 12: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 13: &lt;/span&gt; &lt;span class=rem&gt;// imagine these being completely
separate processes with queues between them&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 14: &lt;/span&gt; processes = &lt;span class=kwrd&gt;new&lt;/span&gt; ActivityHost[]&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 15: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 16: &lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; ActivityHost&amp;lt;ReserveCarActivity&amp;gt;(Send),&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 17: &lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; ActivityHost&amp;lt;ReserveHotelActivity&amp;gt;(Send),&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 18: &lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; ActivityHost&amp;lt;ReserveFlightActivity&amp;gt;(Send)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 19: &lt;/span&gt; };&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 20: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 21: &lt;/span&gt; &lt;span class=rem&gt;// hand off to the first address&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 22: &lt;/span&gt; Send(routingSlip.ProgressUri, routingSlip);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 23: &lt;/span&gt;}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 24: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 25: &lt;/span&gt;&lt;span class=kwrd&gt;static&lt;/span&gt; &lt;span class=kwrd&gt;void&lt;/span&gt; Send(Uri
uri, RoutingSlip routingSlip)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 26: &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 27: &lt;/span&gt; &lt;span class=rem&gt;// this is effectively the network
dispatch&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 28: &lt;/span&gt; &lt;span class=kwrd&gt;foreach&lt;/span&gt; (var process &lt;span class=kwrd&gt;in&lt;/span&gt; processes)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 29: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 30: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (process.AcceptMessage(uri,
routingSlip))&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 31: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 32: &lt;/span&gt; &lt;span class=kwrd&gt;break&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 33: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 34: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 35: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;
&lt;p&gt;
The activities each implement a reservation step and an undo step. Here's the one
for cars:
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre&gt;&lt;span class=lnum&gt; 1: &lt;/span&gt;&lt;span class=kwrd&gt;class&lt;/span&gt; ReserveCarActivity
: Activity&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 2: &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 3: &lt;/span&gt; &lt;span class=kwrd&gt;static&lt;/span&gt; Random rnd = &lt;span class=kwrd&gt;new&lt;/span&gt; Random(2);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 4: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 5: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;override&lt;/span&gt; WorkLog
DoWork(WorkItem workItem)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 6: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 7: &lt;/span&gt; Console.WriteLine(&lt;span class=str&gt;"Reserving car"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 8: &lt;/span&gt; var car = workItem.Arguments[&lt;span class=str&gt;"vehicleType"&lt;/span&gt;];&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 9: &lt;/span&gt; var reservationId = rnd.Next(100000);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 10: &lt;/span&gt; Console.WriteLine(&lt;span class=str&gt;"Reserved car
{0}"&lt;/span&gt;, reservationId);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 11: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; WorkLog(&lt;span class=kwrd&gt;this&lt;/span&gt;, &lt;span class=kwrd&gt;new&lt;/span&gt; WorkResult
{ { &lt;span class=str&gt;"reservationId"&lt;/span&gt;, reservationId } });&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 12: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 13: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 14: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;override&lt;/span&gt; &lt;span class=kwrd&gt;bool&lt;/span&gt; Compensate(WorkLog
item, RoutingSlip routingSlip)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 15: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 16: &lt;/span&gt; var reservationId = item.Result[&lt;span class=str&gt;"reservationId"&lt;/span&gt;];&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 17: &lt;/span&gt; Console.WriteLine(&lt;span class=str&gt;"Cancelled car
{0}"&lt;/span&gt;, reservationId);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 18: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;true&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 19: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 20: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 21: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;override&lt;/span&gt; Uri
WorkItemQueueAddress&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 22: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 23: &lt;/span&gt; get { &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; Uri(&lt;span class=str&gt;"sb://./carReservations"&lt;/span&gt;);
}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 24: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 25: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 26: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;override&lt;/span&gt; Uri
CompensationQueueAddress&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 27: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 28: &lt;/span&gt; get { &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; Uri(&lt;span class=str&gt;"sb://./carCancellactions"&lt;/span&gt;);
}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 29: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 30: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;
&lt;p&gt;
The chaining happens solely through the routing slip. The routing slip is "serializable"
(it's not, pretend that it is) and it's the only piece of information that flows between
the collaborating activities. There is no central coordination. All work is local
on the nodes and once a node is done, it either hands the routing slip forward (on
success) or backward (on failure). For forward progress data, the routing slip has
a queue and for backwards items it maintains a stack. The routing slip also handles
resolving and invoking whatever the "next" thing to call is on the way forward and
backward.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre&gt;&lt;span class=lnum&gt; 1: &lt;/span&gt;&lt;span class=kwrd&gt;class&lt;/span&gt; RoutingSlip&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 2: &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 3: &lt;/span&gt; &lt;span class=kwrd&gt;readonly&lt;/span&gt; Stack&amp;lt;WorkLog&amp;gt;
completedWorkLogs = &lt;span class=kwrd&gt;new&lt;/span&gt; Stack&amp;lt;WorkLog&amp;gt;();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 4: &lt;/span&gt; &lt;span class=kwrd&gt;readonly&lt;/span&gt; Queue&amp;lt;WorkItem&amp;gt;
nextWorkItem = &lt;span class=kwrd&gt;new&lt;/span&gt; Queue&amp;lt;WorkItem&amp;gt;();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 5: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 6: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; RoutingSlip()&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 7: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 8: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 9: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 10: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; RoutingSlip(IEnumerable&amp;lt;WorkItem&amp;gt;
workItems)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 11: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 12: &lt;/span&gt; &lt;span class=kwrd&gt;foreach&lt;/span&gt; (var workItem &lt;span class=kwrd&gt;in&lt;/span&gt; workItems)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 13: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 14: &lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.nextWorkItem.Enqueue(workItem);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 15: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 16: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 17: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 18: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;bool&lt;/span&gt; IsCompleted&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 19: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 20: &lt;/span&gt; get { &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.nextWorkItem.Count
== 0; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 21: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 22: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 23: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;bool&lt;/span&gt; IsInProgress&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 24: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 25: &lt;/span&gt; get { &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.completedWorkLogs.Count
&amp;gt; 0; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 26: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 27: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 28: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;bool&lt;/span&gt; ProcessNext()&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 29: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 30: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (&lt;span class=kwrd&gt;this&lt;/span&gt;.IsCompleted)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 31: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 32: &lt;/span&gt; &lt;span class=kwrd&gt;throw&lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; InvalidOperationException();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 33: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 34: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 35: &lt;/span&gt; var currentItem = &lt;span class=kwrd&gt;this&lt;/span&gt;.nextWorkItem.Dequeue();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 36: &lt;/span&gt; var activity = (Activity)Activator.CreateInstance(currentItem.ActivityType);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 37: &lt;/span&gt; &lt;span class=kwrd&gt;try&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 38: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 39: &lt;/span&gt; var result = activity.DoWork(currentItem);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 40: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (result != &lt;span class=kwrd&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 41: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 42: &lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.completedWorkLogs.Push(result);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 43: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;true&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 44: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 45: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 46: &lt;/span&gt; &lt;span class=kwrd&gt;catch&lt;/span&gt; (Exception e)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 47: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 48: &lt;/span&gt; Console.WriteLine(&lt;span class=str&gt;"Exception {0}"&lt;/span&gt;,
e.Message);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 49: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 50: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;false&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 51: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 52: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 53: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; Uri ProgressUri&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 54: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 55: &lt;/span&gt; get&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 56: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 57: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (IsCompleted)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 58: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 59: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;null&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 60: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 61: &lt;/span&gt; &lt;span class=kwrd&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 62: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 63: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 64: &lt;/span&gt; ((Activity)Activator.CreateInstance(&lt;span class=kwrd&gt;this&lt;/span&gt;.nextWorkItem.Peek().ActivityType)).&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 65: &lt;/span&gt; WorkItemQueueAddress;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 66: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 67: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 68: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 69: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 70: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; Uri CompensationUri&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 71: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 72: &lt;/span&gt; get&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 73: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 74: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (!IsInProgress)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 75: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 76: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt; &lt;span class=kwrd&gt;null&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 77: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 78: &lt;/span&gt; &lt;span class=kwrd&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 79: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 80: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 81: &lt;/span&gt; ((Activity)Activator.CreateInstance(&lt;span class=kwrd&gt;this&lt;/span&gt;.completedWorkLogs.Peek().ActivityType)).&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 82: &lt;/span&gt; CompensationQueueAddress;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 83: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 84: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 85: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 86: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 87: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;bool&lt;/span&gt; UndoLast()&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 88: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 89: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (!&lt;span class=kwrd&gt;this&lt;/span&gt;.IsInProgress)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 90: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 91: &lt;/span&gt; &lt;span class=kwrd&gt;throw&lt;/span&gt; &lt;span class=kwrd&gt;new&lt;/span&gt; InvalidOperationException();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 92: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 93: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 94: &lt;/span&gt; var currentItem = &lt;span class=kwrd&gt;this&lt;/span&gt;.completedWorkLogs.Pop();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 95: &lt;/span&gt; var activity = (Activity)Activator.CreateInstance(currentItem.ActivityType);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 96: &lt;/span&gt; &lt;span class=kwrd&gt;try&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 97: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 98: &lt;/span&gt; &lt;span class=kwrd&gt;return&lt;/span&gt; activity.Compensate(currentItem, &lt;span class=kwrd&gt;this&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 99: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 100: &lt;/span&gt; &lt;span class=kwrd&gt;catch&lt;/span&gt; (Exception e)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 101: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 102: &lt;/span&gt; Console.WriteLine(&lt;span class=str&gt;"Exception {0}"&lt;/span&gt;,
e.Message);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 103: &lt;/span&gt; &lt;span class=kwrd&gt;throw&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 104: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 105: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 106: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 107: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;
&lt;p&gt;
The local work&amp;nbsp; and making the decisions is encapsulated in the ActivityHost,
which calls ProcessNext() on the routing slip to resolve the next activity and call
its DoWork() function on the way forward or will resolve the last executed activity
on the way back and invoke its Compensate() function. Again, there's nothing centralized
here; all that work hinges on the routing slip and the three activities and their
execution is completely disjoint.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre&gt;&lt;span class=lnum&gt; 1: &lt;/span&gt;&lt;span class=kwrd&gt;abstract&lt;/span&gt; &lt;span class=kwrd&gt;class&lt;/span&gt; ActivityHost&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 2: &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 3: &lt;/span&gt; Action&amp;lt;Uri, RoutingSlip&amp;gt; send;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 4: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 5: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; ActivityHost(Action&amp;lt;Uri,
RoutingSlip&amp;gt; send)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 6: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 7: &lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.send = send;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 8: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 9: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 10: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;void&lt;/span&gt; ProcessForwardMessage(RoutingSlip
routingSlip)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 11: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 12: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (!routingSlip.IsCompleted)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 13: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 14: &lt;/span&gt; &lt;span class=rem&gt;// if the current step is successful,
proceed&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 15: &lt;/span&gt; &lt;span class=rem&gt;// otherwise go to the Unwind path&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 16: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (routingSlip.ProcessNext())&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 17: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 18: &lt;/span&gt; &lt;span class=rem&gt;// recursion stands for passing
context via message&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 19: &lt;/span&gt; &lt;span class=rem&gt;// the routing slip can be fully
serialized and passed&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 20: &lt;/span&gt; &lt;span class=rem&gt;// between systems. &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 21: &lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.send(routingSlip.ProgressUri,
routingSlip);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 22: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 23: &lt;/span&gt; &lt;span class=kwrd&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 24: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 25: &lt;/span&gt; &lt;span class=rem&gt;// pass message to unwind message
route&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 26: &lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.send(routingSlip.CompensationUri,
routingSlip);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 27: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 28: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 29: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 30: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 31: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;void&lt;/span&gt; ProcessBackwardMessage(RoutingSlip
routingSlip)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 32: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 33: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (routingSlip.IsInProgress)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 34: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 35: &lt;/span&gt; &lt;span class=rem&gt;// UndoLast can put new work on
the routing slip&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 36: &lt;/span&gt; &lt;span class=rem&gt;// and return false to go back
on the forward &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 37: &lt;/span&gt; &lt;span class=rem&gt;// path&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 38: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (routingSlip.UndoLast())&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 39: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 40: &lt;/span&gt; &lt;span class=rem&gt;// recursion stands for passing
context via message&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 41: &lt;/span&gt; &lt;span class=rem&gt;// the routing slip can be fully
serialized and passed&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 42: &lt;/span&gt; &lt;span class=rem&gt;// between systems &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 43: &lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.send(routingSlip.CompensationUri,
routingSlip);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 44: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 45: &lt;/span&gt; &lt;span class=kwrd&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 46: &lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 47: &lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.send(routingSlip.ProgressUri,
routingSlip);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 48: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 49: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 50: &lt;/span&gt; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 51: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 52: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;abstract&lt;/span&gt; &lt;span class=kwrd&gt;bool&lt;/span&gt; AcceptMessage(Uri
uri, RoutingSlip routingSlip);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=lnum&gt; 53: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
That's a Saga.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1e55de13-92c3-46ed-b01c-dcda6cc5ecf6" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,1e55de13-92c3-46ed-b01c-dcda6cc5ecf6.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=88aa1fbe-083b-4859-807a-eb0cb85547d2</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,88aa1fbe-083b-4859-807a-eb0cb85547d2.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,88aa1fbe-083b-4859-807a-eb0cb85547d2.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=88aa1fbe-083b-4859-807a-eb0cb85547d2</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Greg <a href="http://goodenoughsoftware.net/2012/03/02/cqrs/" target="_blank">says
what it’s not</a>, and since he didn’t use the opportunity to also succinctly express
what it <em>is</em>, I helped him out in the comments: 
</p>
        <p>
          <em>CQRS ("Command-Query Responsibility Segregation") is a simple pattern that strictly
segregates the responsibility of handling command input into an autonomous system
from the responsibility of handling side-effect-free query/read access on the same
system. Consequently, the decoupling allows for any number of homogeneous or heterogeneous
query/read modules to be paired with a command processor and this principle presents
a very suitable foundation for event sourcing, eventual-consistency state replication/fan-out
and, thus, high-scale read access. In simple terms: You don’t service queries via
the same module of a service that you process commands through. For REST heads: GET
wires to a different thing from what PUT/POST/DELETE wire up to.</em>
        </p>
        <p>
Martin Fowler has a nice discussion <a href="http://martinfowler.com/bliki/CQRS.html" target="_blank">here</a>,
with pictures. Udi Dahan has <a href="http://www.udidahan.com/2009/12/09/clarified-cqrs/" target="_blank">another
nice description</a>, also with pictures. To say it in yet another way, the key point
of the pattern is that the read and write paths in a system are entirely separate.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=88aa1fbe-083b-4859-807a-eb0cb85547d2" />
      </body>
      <title>What is CQRS?</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,88aa1fbe-083b-4859-807a-eb0cb85547d2.aspx</guid>
      <link>http://vasters.com/clemensv/2012/03/05/What+Is+CQRS.aspx</link>
      <pubDate>Mon, 05 Mar 2012 23:00:11 GMT</pubDate>
      <description>&lt;p&gt;
Greg &lt;a href="http://goodenoughsoftware.net/2012/03/02/cqrs/" target=_blank&gt;says what
it’s not&lt;/a&gt;, and since he didn’t use the opportunity to also succinctly express what
it &lt;em&gt;is&lt;/em&gt;, I helped him out in the comments: 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;CQRS ("Command-Query Responsibility Segregation") is a simple pattern that strictly
segregates the responsibility of handling command input into an autonomous system
from the responsibility of handling side-effect-free query/read access on the same
system. Consequently, the decoupling allows for any number of homogeneous or heterogeneous
query/read modules to be paired with a command processor and this principle presents
a very suitable foundation for event sourcing, eventual-consistency state replication/fan-out
and, thus, high-scale read access. In simple terms: You don’t service queries via
the same module of a service that you process commands through. For REST heads: GET
wires to a different thing from what PUT/POST/DELETE wire up to.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Martin Fowler has a nice discussion &lt;a href="http://martinfowler.com/bliki/CQRS.html" target=_blank&gt;here&lt;/a&gt;,
with pictures. Udi Dahan has &lt;a href="http://www.udidahan.com/2009/12/09/clarified-cqrs/" target=_blank&gt;another
nice description&lt;/a&gt;, also with pictures. To say it in yet another way, the key point
of the pattern is that the read and write paths in a system are entirely separate.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=88aa1fbe-083b-4859-807a-eb0cb85547d2" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,88aa1fbe-083b-4859-807a-eb0cb85547d2.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=45ae933a-3c7e-4863-98e9-c017673b3b55</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,45ae933a-3c7e-4863-98e9-c017673b3b55.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,45ae933a-3c7e-4863-98e9-c017673b3b55.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=45ae933a-3c7e-4863-98e9-c017673b3b55</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I answered 4 questions in Richard Seroter’s series of interviews with folks working
on connect systems. See the <a href="http://seroter.wordpress.com/2011/12/01/interview-series-four-questions-with-clemens-vasters/">Q&amp;A
here</a>.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=45ae933a-3c7e-4863-98e9-c017673b3b55" />
      </body>
      <title>4 Questions</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,45ae933a-3c7e-4863-98e9-c017673b3b55.aspx</guid>
      <link>http://vasters.com/clemensv/2011/12/01/4+Questions.aspx</link>
      <pubDate>Thu, 01 Dec 2011 17:38:37 GMT</pubDate>
      <description>&lt;p&gt;
I answered 4 questions in Richard Seroter’s series of interviews with folks working
on connect systems. See the &lt;a href="http://seroter.wordpress.com/2011/12/01/interview-series-four-questions-with-clemens-vasters/"&gt;Q&amp;amp;A
here&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=45ae933a-3c7e-4863-98e9-c017673b3b55" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,45ae933a-3c7e-4863-98e9-c017673b3b55.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=b2e9e279-8ab3-4126-905a-25650c57a468</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,b2e9e279-8ab3-4126-905a-25650c57a468.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,b2e9e279-8ab3-4126-905a-25650c57a468.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=b2e9e279-8ab3-4126-905a-25650c57a468</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Elastic and dynamic multitenant cloud environments have characteristics that make
traditional failure management mechanisms using coordinated 2-phase transactions a
suboptimal choice. The common 2-phase commit protocols depend on a number of parties
enlisted into a transaction making hard promises on the expected outcome of their
slice a transaction. Those promises are difficult to keep in an environment where
systems may go down at any time with their local state vanishing, where not all party
trust each other, where significant latency may be involved, and network connectivity
cannot be assumed to be reliable. 2-phase-commit is also not a good choice for operations
that take significant amounts of time and span a significant amount of resources,
because such a coordinated transaction may adversely affect the availability of said
resources, especially in cases where the solution is a high-density multitenant solution
where virtualized, and conceptually isolated resources are collocated on the same
base resources. In such a case, database locks and locks on other resources to satisfy
coordinated transaction promises may easily break the isolation model of a multitenant
system and have one tenant affect the other.
</p>
        <p>
Therefore, failure management – and this is ultimately what transactions are about
– requires a somewhat different approach in cloud environments and other scalable
distributed systems with similar characteristics. 
</p>
        <p>
To find a suitable set of alternative approaches, let’s quickly dissect what goes
on in a distributed transaction: 
</p>
        <p>
To start, two or more parties ‘enlist’ into a shared transaction scope performing
some coordinated work that’s commonly motivated by a shared notion of a ‘job’ that 
needs to be executed. The goal of having a shared transaction scope is that the overall
system will remain correct and consistent in both the success and the failure cases.
Consistency in the success case is trivial. All participating parties could complete
their slice of the job that had to be done. Consistency in the failure case is more
interesting. If any party fails in doing their part of the job, the system will end
up in a state that is not consistent. If you were trying to book a travel package
and ticketing with the airline failed, you may end up with a hotel and a car, but
no flight. In order to prevent that, a ‘classic’ distributed transaction asks the
participants to make promises on the outcome of the transaction as the transaction
is going on. 
</p>
        <p>
As all participating parties have tentatively completed but not finalized their work,
the distributed transaction goes into a voting phase where every participant is asked
whether it could tentatively complete its portion of the job and whether it can furthermore
guarantee with a very high degree of certainty that it can finalize the job outcome
and make it effective when asked to do so. Imagine a store clerk who puts an item
on the counter that you’d like to purchase – you’ll show him your $10 and ask for
a promise that he will hand you the item if you give him the money – and vice versa. 
</p>
        <p>
Finally, once all parties have made their promises and agreed that the job can be
finalized, they are told to do so.
</p>
        <p>
There are two big interesting things to observe about the 2-phase-commit (2PC) distributed
transaction model that I just described: First, It’s incredibly simple from a developer’s
perspective because the transaction outcome negotiation is externalized and happens
as ‘magic’. Second, it’s not resembling anything that happens in real life and that
should be somewhat suspicious. You may have noticed that there was no neutral escrow
agent present when you bought the case of beverages at the store for $10 two paragraphs
earlier. 
</p>
        <p>
The grand canonical example for 2PC transactions is a bank account transfer. You debit
one account and credit another. These two operations need to succeed or fail together
because otherwise you are either creating or destroying money (which is illegal, by
the way). So that’s the example that’s very commonly used to illustrate 2PC transactions.
The catch is – that’s not how it really works, at all. Getting money from one bank
account to another bank account is a fairly complicated affair that touches a ton
of other accounts. More importantly, it’s not a synchronous fail-together/success-together
scenario. Instead, principles of accounting apply (surprise!). When a transfer is
initiated, let’s say in online banking, the transfer is recorded in form of a message
for submission into the accounting system and the debit is recorded in the account
as a ‘pending’ transaction that affects the displayed balance. From the user’s perspective,
the transaction is ’done’, but factually nothing has happened, yet. Eventually, the
accounting system will get the message and start performing the transfer, which often
causes a cascade of operations, many of them yielding further messages, including
booking into clearing accounts and notifying the other bank of the transfer. The principle
here is that all progress is forward. If an operation doesn’t work for some technical
reason it can be retried once the technical reason is resolved. If operation fails
for a business reason, the operation can be aborted – but not by annihilating previous
work, but by doing the inverse of previous work. If an account was credited, that
credit is annulled with a debit of the same amount. For some types of failed transactions, 
the ‘inverse’ operation may not be fully symmetric but may result in extra actions
like imposing penalty fees. In fact, in accounting, annihilating any work is illegal
– ‘delete’ and ‘update’ are a great way to end up in prison. 
</p>
        <p>
As all the operations occur that eventually lead to the completion or failure of the
grand complex operation that is a bank transfer, the one thing we’ll be looking to
avoid is to be in any kind of ‘doubt’ of the state of the system. All participants
must be able to have a great degree of confidence in their knowledge about the success
or failure of their respective action. No shots into the dark. There’s no maybe. Succeed
or fail. 
</p>
        <p>
That said, “fail” is a funny thing is distributed systems because it happens quite
a bit. In many cases “fail” isn’t something that a bit of patience can’t fix. Which
means that teaching the system some patience and tenacity is probably a good idea
instead of giving up too easily. So if an operation fails because it runs into a database
deadlock or the database is offline or the network is down or the local machine’s
network adapter just got electrocuted that’s all not necessarily a reason to fail
the operation. That’s a reason to write an alert into a log and call for help for
someone to fix the environment condition. 
</p>
        <p>
If we zoom into an ‘operation’ here, we might see a message that we retrieve from
some sort of reliable queue or some other kind of message store and subsequently an
update of system state based on message. Once the state has been successfully updated,
which may mean that we’ve inserted a new database record, we can tell the message
system that the message has been processed and that it can be discarded. That’s the
happy case. 
</p>
        <p>
Let’s say we take the message and as the process wants to walk up the database the
power shuts off. Click. Darkness. Not a problem. Assuming the messaging system supports
a ‘peek/lock’ model that allows the process to first take the message and only remove
it from the queue once processing has been completed, the message will reappear on
the queue after the lock has expired and the operation can be retried, possibly on
a different node. That model holds true for all failures of the operation through
to and in the database. If the operation fails due to some transient condition (including
the network card smoking out, see above), the message is either explicitly abandoned
by the process or returns into the queue by ways of a lock timeout.  If the operation
fails because something is really logically wrong, like trying to ship a product out
of the inventory that’s factually out of stock, we’ll have to take some forward action
to deal with that. We’ll get to that in a bit. 
</p>
        <p>
Assuming the operation succeeded, the next tricky waypoint is failure after success,
meaning that the database operation succeeded, but the message subsequently can’t
be flagged as completed and thus can’t be removed from the queue. That situation would
potentially lead to another delivery of the message even though the job has already
been completed and therefore would cause the job to be executed again – which is only
a problem if the system isn’t expecting that, or, in fancier terms, if it’s not ‘idempotent’.
If the job is updating a record to absolute values and the particular process/module/procedure
is the only avenue to perform that update (meaning there are no competing writers
elsewhere), doing that update again and again and again is just fine. That’s natural
idempotency. If the job is inserting a record, the job should contain enough information,
such as a causality or case or logical transaction identifier that allows the process
to figure out whether the desired record has already been inserted and if that’s the
case it should do nothing, consider its own action a duplicate and just act as if
it succeeded. 
</p>
        <p>
Checkpoint: With what I said in the last two paragraphs, you can establish pretty
good confidence about failure or success of individual operations that are driven
by messages. You fail and retry, you fail and take forward action, or you succeed
and take steps to avoid retrying even if the system presents the same job again. There’s
very little room for doubt. So that’s good.
</p>
        <p>
The ‘forward action’ that results from failure is often referred to as ‘compensation’,
but that’s a bit simplistic. The forward action resulting from running into the warehouse
with the belief that there’s still product present while the shelf is factually empty
isn’t to back out and cancel the order (unless you’re doing a firesale of a touch
tablet your management just killed). Instead, you notify the customer of the shipping
delay, flag a correction of the inventory levels, and put the item on backorder. For
the most part, pure ‘compensation’ doesn’t really exist. With every action, the system
ends up in a consistent state. It’s just that some states are more convenient than
others and there are some state for which the system has a good answer and some states
for which it doesn’t. If the system ends up in a dead end street and just wants to
sit down and cry because nobody told it what to do now, it should phone home and ask
for human intervention. That’s fine and likely a wise strategy in weird edge cases. 
</p>
        <p>
Initiating the ‘forward action’ and, really, any action in a system that’s using messaging
as its lifeline and as a backplane for failure resilience as I’m describing it here
is not entirely without failure risk in itself. It’s possible that you want to initiate
an action and can’t reach the messaging system or sending the message fails for some
other reason. Here again, patience and tenacity are a good idea. If we can’t send,
our overall operation is considered failed and we won’t flag the initiating message
as completed. That will cause the job to show up again, but since we’ve got idempotency
in the database that operation will again succeed (even if by playing dead) or fail
and we will have the same outcome allowing us to retry the send. If it looks like
we can send but sending fails sometime during the operation, there might be doubt
about whether we sent the message. Since doubt is a problem and we shouldn’t send
the same message twice, duplicate detection in the messaging system can help suppressing
a duplicate so that it never shows up at the receiver. That allows the sender to confidently
resend if it’s in doubt about success in a prior incarnation of processing the same
message.
</p>
        <p>
Checkpoint: We now also can establish pretty good confidence about initiating forward
action or any other action in the system given if the ‘current’ action is following
the principles described above.
</p>
        <p>
So far I’ve talked about individual actions and also about chains of actions, albeit
just in the failure case. Obviously the same applies to success cases where you want
to do something ‘next’ once you’re done with ‘this’. 
</p>
        <p>
Now let’s assume you want to do multiple things in parallel, like updating multiple
stores as part of executing a single job – which gets us back to the distributed transaction
scenario discussed earlier. What helps in these cases is if the messaging system supports
‘topics’ that allow dropping a message (the job) into the messaging system once and
serve the message to each participant in the composite activity via their own subscription
on the topic. Since the messaging system is internally transactional it will guarantee
that each message that is successfully submitted will indeed appear on each subscription
so it ensures the distribution. With that, the failure handling story for each slice
of the composite job turns into the same model that I’ve been explaining above. Each
participant can be patient and tenacious when it comes to transient error conditions.
In hard failure cases, the forward action can be a notification to the initiator that
will then have to decide how to progress forward, including annulling or otherwise
invoking forward actions activities that have been executed in parallel. In the aforementioned
case of a ticketing failure that means that the ticketing module throws its hands
up and the module responsible for booking the travel package either decides to bubble
the case to the customer or an operator leaving the remaining reservations intact
or to cancel the reservations for the car and the hotel that have been made in parallel.
Should two out of three or more participants’ operations fail and each report up to
the initiator, the initiator can either keep track of whether it already took corrective
forward action on the third participant or, in doubt, the idempotency rule should
avoid doing the same thing twice.
</p>
        <p>
The model described here is loosely based on the notion of ‘Sagas’, which were first
described in a 1987 ACM paper by Hector Garcia-Molina and Kenneth Salem, so this isn’t
grand news. However, the notion of such Sagas is only now really gaining momentum
with long-running and far distributed transactions becoming more commonplace, so it’s
well worth to drag the model further out into the limelight and give it coverage.
The original paper on Sagas is still assuming that the individual steps can be encapsulated
in a regular transaction, which may not even be the case in the cloud and with infrastructures
that don’t have inherent transaction support. The role of the messaging system with
the capabilities mentioned above is to help compensate for the absence of that support. 
</p>
        <p>
… to be continued …
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b2e9e279-8ab3-4126-905a-25650c57a468" />
      </body>
      <title>Achieving Transactional Behavior with Messaging</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,b2e9e279-8ab3-4126-905a-25650c57a468.aspx</guid>
      <link>http://vasters.com/clemensv/2011/10/06/Achieving+Transactional+Behavior+With+Messaging.aspx</link>
      <pubDate>Thu, 06 Oct 2011 21:10:14 GMT</pubDate>
      <description>&lt;p&gt;
Elastic and dynamic multitenant cloud environments have characteristics that make
traditional failure management mechanisms using coordinated 2-phase transactions a
suboptimal choice. The common 2-phase commit protocols depend on a number of parties
enlisted into a transaction making hard promises on the expected outcome of their
slice a transaction. Those promises are difficult to keep in an environment where
systems may go down at any time with their local state vanishing, where not all party
trust each other, where significant latency may be involved, and network connectivity
cannot be assumed to be reliable. 2-phase-commit is also not a good choice for operations
that take significant amounts of time and span a significant amount of resources,
because such a coordinated transaction may adversely affect the availability of said
resources, especially in cases where the solution is a high-density multitenant solution
where virtualized, and conceptually isolated resources are collocated on the same
base resources. In such a case, database locks and locks on other resources to satisfy
coordinated transaction promises may easily break the isolation model of a multitenant
system and have one tenant affect the other.
&lt;/p&gt;
&lt;p&gt;
Therefore, failure management – and this is ultimately what transactions are about
– requires a somewhat different approach in cloud environments and other scalable
distributed systems with similar characteristics. 
&lt;/p&gt;
&lt;p&gt;
To find a suitable set of alternative approaches, let’s quickly dissect what goes
on in a distributed transaction: 
&lt;/p&gt;
&lt;p&gt;
To start, two or more parties ‘enlist’ into a shared transaction scope performing
some coordinated work that’s commonly motivated by a shared notion of a ‘job’ that&amp;nbsp;
needs to be executed. The goal of having a shared transaction scope is that the overall
system will remain correct and consistent in both the success and the failure cases.
Consistency in the success case is trivial. All participating parties could complete
their slice of the job that had to be done. Consistency in the failure case is more
interesting. If any party fails in doing their part of the job, the system will end
up in a state that is not consistent. If you were trying to book a travel package
and ticketing with the airline failed, you may end up with a hotel and a car, but
no flight. In order to prevent that, a ‘classic’ distributed transaction asks the
participants to make promises on the outcome of the transaction as the transaction
is going on. 
&lt;/p&gt;
&lt;p&gt;
As all participating parties have tentatively completed but not finalized their work,
the distributed transaction goes into a voting phase where every participant is asked
whether it could tentatively complete its portion of the job and whether it can furthermore
guarantee with a very high degree of certainty that it can finalize the job outcome
and make it effective when asked to do so. Imagine a store clerk who puts an item
on the counter that you’d like to purchase – you’ll show him your $10 and ask for
a promise that he will hand you the item if you give him the money – and vice versa. 
&lt;/p&gt;
&lt;p&gt;
Finally, once all parties have made their promises and agreed that the job can be
finalized, they are told to do so.
&lt;/p&gt;
&lt;p&gt;
There are two big interesting things to observe about the 2-phase-commit (2PC) distributed
transaction model that I just described: First, It’s incredibly simple from a developer’s
perspective because the transaction outcome negotiation is externalized and happens
as ‘magic’. Second, it’s not resembling anything that happens in real life and that
should be somewhat suspicious. You may have noticed that there was no neutral escrow
agent present when you bought the case of beverages at the store for $10 two paragraphs
earlier. 
&lt;/p&gt;
&lt;p&gt;
The grand canonical example for 2PC transactions is a bank account transfer. You debit
one account and credit another. These two operations need to succeed or fail together
because otherwise you are either creating or destroying money (which is illegal, by
the way). So that’s the example that’s very commonly used to illustrate 2PC transactions.
The catch is – that’s not how it really works, at all. Getting money from one bank
account to another bank account is a fairly complicated affair that touches a ton
of other accounts. More importantly, it’s not a synchronous fail-together/success-together
scenario. Instead, principles of accounting apply (surprise!). When a transfer is
initiated, let’s say in online banking, the transfer is recorded in form of a message
for submission into the accounting system and the debit is recorded in the account
as a ‘pending’ transaction that affects the displayed balance. From the user’s perspective,
the transaction is ’done’, but factually nothing has happened, yet. Eventually, the
accounting system will get the message and start performing the transfer, which often
causes a cascade of operations, many of them yielding further messages, including
booking into clearing accounts and notifying the other bank of the transfer. The principle
here is that all progress is forward. If an operation doesn’t work for some technical
reason it can be retried once the technical reason is resolved. If operation fails
for a business reason, the operation can be aborted – but not by annihilating previous
work, but by doing the inverse of previous work. If an account was credited, that
credit is annulled with a debit of the same amount. For some types of failed transactions,&amp;nbsp;
the ‘inverse’ operation may not be fully symmetric but may result in extra actions
like imposing penalty fees. In fact, in accounting, annihilating any work is illegal
– ‘delete’ and ‘update’ are a great way to end up in prison. 
&lt;/p&gt;
&lt;p&gt;
As all the operations occur that eventually lead to the completion or failure of the
grand complex operation that is a bank transfer, the one thing we’ll be looking to
avoid is to be in any kind of ‘doubt’ of the state of the system. All participants
must be able to have a great degree of confidence in their knowledge about the success
or failure of their respective action. No shots into the dark. There’s no maybe. Succeed
or fail. 
&lt;/p&gt;
&lt;p&gt;
That said, “fail” is a funny thing is distributed systems because it happens quite
a bit. In many cases “fail” isn’t something that a bit of patience can’t fix. Which
means that teaching the system some patience and tenacity is probably a good idea
instead of giving up too easily. So if an operation fails because it runs into a database
deadlock or the database is offline or the network is down or the local machine’s
network adapter just got electrocuted that’s all not necessarily a reason to fail
the operation. That’s a reason to write an alert into a log and call for help for
someone to fix the environment condition. 
&lt;/p&gt;
&lt;p&gt;
If we zoom into an ‘operation’ here, we might see a message that we retrieve from
some sort of reliable queue or some other kind of message store and subsequently an
update of system state based on message. Once the state has been successfully updated,
which may mean that we’ve inserted a new database record, we can tell the message
system that the message has been processed and that it can be discarded. That’s the
happy case. 
&lt;/p&gt;
&lt;p&gt;
Let’s say we take the message and as the process wants to walk up the database the
power shuts off. Click. Darkness. Not a problem. Assuming the messaging system supports
a ‘peek/lock’ model that allows the process to first take the message and only remove
it from the queue once processing has been completed, the message will reappear on
the queue after the lock has expired and the operation can be retried, possibly on
a different node. That model holds true for all failures of the operation through
to and in the database. If the operation fails due to some transient condition (including
the network card smoking out, see above), the message is either explicitly abandoned
by the process or returns into the queue by ways of a lock timeout.&amp;nbsp; If the operation
fails because something is really logically wrong, like trying to ship a product out
of the inventory that’s factually out of stock, we’ll have to take some forward action
to deal with that. We’ll get to that in a bit. 
&lt;/p&gt;
&lt;p&gt;
Assuming the operation succeeded, the next tricky waypoint is failure after success,
meaning that the database operation succeeded, but the message subsequently can’t
be flagged as completed and thus can’t be removed from the queue. That situation would
potentially lead to another delivery of the message even though the job has already
been completed and therefore would cause the job to be executed again – which is only
a problem if the system isn’t expecting that, or, in fancier terms, if it’s not ‘idempotent’.
If the job is updating a record to absolute values and the particular process/module/procedure
is the only avenue to perform that update (meaning there are no competing writers
elsewhere), doing that update again and again and again is just fine. That’s natural
idempotency. If the job is inserting a record, the job should contain enough information,
such as a causality or case or logical transaction identifier that allows the process
to figure out whether the desired record has already been inserted and if that’s the
case it should do nothing, consider its own action a duplicate and just act as if
it succeeded. 
&lt;/p&gt;
&lt;p&gt;
Checkpoint: With what I said in the last two paragraphs, you can establish pretty
good confidence about failure or success of individual operations that are driven
by messages. You fail and retry, you fail and take forward action, or you succeed
and take steps to avoid retrying even if the system presents the same job again. There’s
very little room for doubt. So that’s good.
&lt;/p&gt;
&lt;p&gt;
The ‘forward action’ that results from failure is often referred to as ‘compensation’,
but that’s a bit simplistic. The forward action resulting from running into the warehouse
with the belief that there’s still product present while the shelf is factually empty
isn’t to back out and cancel the order (unless you’re doing a firesale of a touch
tablet your management just killed). Instead, you notify the customer of the shipping
delay, flag a correction of the inventory levels, and put the item on backorder. For
the most part, pure ‘compensation’ doesn’t really exist. With every action, the system
ends up in a consistent state. It’s just that some states are more convenient than
others and there are some state for which the system has a good answer and some states
for which it doesn’t. If the system ends up in a dead end street and just wants to
sit down and cry because nobody told it what to do now, it should phone home and ask
for human intervention. That’s fine and likely a wise strategy in weird edge cases. 
&lt;/p&gt;
&lt;p&gt;
Initiating the ‘forward action’ and, really, any action in a system that’s using messaging
as its lifeline and as a backplane for failure resilience as I’m describing it here
is not entirely without failure risk in itself. It’s possible that you want to initiate
an action and can’t reach the messaging system or sending the message fails for some
other reason. Here again, patience and tenacity are a good idea. If we can’t send,
our overall operation is considered failed and we won’t flag the initiating message
as completed. That will cause the job to show up again, but since we’ve got idempotency
in the database that operation will again succeed (even if by playing dead) or fail
and we will have the same outcome allowing us to retry the send. If it looks like
we can send but sending fails sometime during the operation, there might be doubt
about whether we sent the message. Since doubt is a problem and we shouldn’t send
the same message twice, duplicate detection in the messaging system can help suppressing
a duplicate so that it never shows up at the receiver. That allows the sender to confidently
resend if it’s in doubt about success in a prior incarnation of processing the same
message.
&lt;/p&gt;
&lt;p&gt;
Checkpoint: We now also can establish pretty good confidence about initiating forward
action or any other action in the system given if the ‘current’ action is following
the principles described above.
&lt;/p&gt;
&lt;p&gt;
So far I’ve talked about individual actions and also about chains of actions, albeit
just in the failure case. Obviously the same applies to success cases where you want
to do something ‘next’ once you’re done with ‘this’. 
&lt;/p&gt;
&lt;p&gt;
Now let’s assume you want to do multiple things in parallel, like updating multiple
stores as part of executing a single job – which gets us back to the distributed transaction
scenario discussed earlier. What helps in these cases is if the messaging system supports
‘topics’ that allow dropping a message (the job) into the messaging system once and
serve the message to each participant in the composite activity via their own subscription
on the topic. Since the messaging system is internally transactional it will guarantee
that each message that is successfully submitted will indeed appear on each subscription
so it ensures the distribution. With that, the failure handling story for each slice
of the composite job turns into the same model that I’ve been explaining above. Each
participant can be patient and tenacious when it comes to transient error conditions.
In hard failure cases, the forward action can be a notification to the initiator that
will then have to decide how to progress forward, including annulling or otherwise
invoking forward actions activities that have been executed in parallel. In the aforementioned
case of a ticketing failure that means that the ticketing module throws its hands
up and the module responsible for booking the travel package either decides to bubble
the case to the customer or an operator leaving the remaining reservations intact
or to cancel the reservations for the car and the hotel that have been made in parallel.
Should two out of three or more participants’ operations fail and each report up to
the initiator, the initiator can either keep track of whether it already took corrective
forward action on the third participant or, in doubt, the idempotency rule should
avoid doing the same thing twice.
&lt;/p&gt;
&lt;p&gt;
The model described here is loosely based on the notion of ‘Sagas’, which were first
described in a 1987 ACM paper by Hector Garcia-Molina and Kenneth Salem, so this isn’t
grand news. However, the notion of such Sagas is only now really gaining momentum
with long-running and far distributed transactions becoming more commonplace, so it’s
well worth to drag the model further out into the limelight and give it coverage.
The original paper on Sagas is still assuming that the individual steps can be encapsulated
in a regular transaction, which may not even be the case in the cloud and with infrastructures
that don’t have inherent transaction support. The role of the messaging system with
the capabilities mentioned above is to help compensate for the absence of that support. 
&lt;/p&gt;
&lt;p&gt;
… to be continued …
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b2e9e279-8ab3-4126-905a-25650c57a468" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,b2e9e279-8ab3-4126-905a-25650c57a468.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=981f28ab-0743-4c34-9130-8811a8d523da</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,981f28ab-0743-4c34-9130-8811a8d523da.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,981f28ab-0743-4c34-9130-8811a8d523da.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=981f28ab-0743-4c34-9130-8811a8d523da</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
From //build in Anaheim
</p>
        <iframe style="WIDTH: 960px; HEIGHT: 544px" src="http://channel9.msdn.com/Events/BUILD/BUILD2011/SAC-862T/player?w=960&amp;h=544" frameborder="0" scrolling="no">
        </iframe>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=981f28ab-0743-4c34-9130-8811a8d523da" />
      </body>
      <title>Building loosely-coupled Apps with Windows Azure Service Bus Topics and Queues</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,981f28ab-0743-4c34-9130-8811a8d523da.aspx</guid>
      <link>http://vasters.com/clemensv/2011/09/16/Building+Looselycoupled+Apps+With+Windows+Azure+Service+Bus+Topics+And+Queues.aspx</link>
      <pubDate>Fri, 16 Sep 2011 14:49:01 GMT</pubDate>
      <description>&lt;p&gt;
From //build in Anaheim
&lt;/p&gt;
&lt;iframe style="WIDTH: 960px; HEIGHT: 544px" src="http://channel9.msdn.com/Events/BUILD/BUILD2011/SAC-862T/player?w=960&amp;amp;h=544" frameborder=0 scrolling=no&gt;
&lt;/iframe&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=981f28ab-0743-4c34-9130-8811a8d523da" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,981f28ab-0743-4c34-9130-8811a8d523da.aspx</comments>
      <category>AppFabric</category>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology/ISB</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=83f937f7-b838-43d0-ad61-74605eceafa2</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,83f937f7-b838-43d0-ad61-74605eceafa2.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,83f937f7-b838-43d0-ad61-74605eceafa2.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=83f937f7-b838-43d0-ad61-74605eceafa2</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p align="justify">
As our team was starting to transform our parts of the Azure Services Platform from
a CTP ‘labs’ service exploring features into a full-on commercial service, it started
to dawn on us that we had set ourselves up for writing a bunch of ‘enterprise apps’.
The shiny parts of Service Bus and Access Control that we parade around are all about
user-facing features, but if I look back at the work we had to go from a toy service
to a commercial offering, I’d guess that 80%-90% of the effort went into aspects like
infrastructure, deployment, upgradeability, billing, provisioning, throttling, quotas,
security hardening, and service optimization. The lesson there was: when you’re boarding
the train to shipping a V1, you don’t load new features on that train –  you
rather throw some off. 
</p>
        <p align="justify">
The most interesting challenge for these infrastructure apps sitting on the backend
was that we didn’t have much solid ground to stand on. Remember – these were very
early days, so we couldn’t use SQL Azure since the folks over in SQL were on a pretty
heroic schedule themselves and didn’t want to take on any external dependencies even
from close friends. We also couldn’t use any of the capabilities of our own bits because
building infrastructure for your features on your features would just be plain dumb.
And while we could use capabilities of the Windows Azure platform we were building
on, a lot of those parts still had rough edges as those folks were going through a
lot of the same that we went through. In those days, the table store would be very
moody, the queue store would sometimes swallow or duplicate messages, the Azure fabric
controller would occasionally go around and kill things. All normal –  bugs.
</p>
        <p align="justify">
So under those circumstances we had to figure out the architecture for some subsystems
where we need to do a set of coordinated action across a distributed set of resources
– a distributed transaction or saga of sorts. The architecture had a few simple goals:
when we get an activation request, we must not fumble that request under any circumstance,
we must run the job to completion for all resources and, at the same time, we need
to minimize any potential for required operator intervention, i.e. if something goes
wrong, the system better knows how to deal with it – at best it should self-heal. 
</p>
        <p align="justify">
My solution to that puzzle is a pattern I call “Scheduler-Agent-Supervisor Pattern”
or, short, “Supervisor Pattern”. We keep finding applications for this pattern in
different places, so I think it’s worth writing about it in generic terms – even without
going into the details of our system.
</p>
        <p align="justify">
The pattern foots on two seemingly odd and very related assumptions: <em>‘</em><strong><em>the
system is perfect’</em></strong>and<strong><em>‘all error conditions are transient’</em>.</strong> As
a consequence, the architecture has some character traits of a toddler. It’s generally
happily optimistic and gets very grumpy, very quickly when things go wrong – to the
point that it will simply drop everything and run away screaming. It’s very precisely
like that, in fact.
</p>
        <p>
          <a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_2.png">
            <img style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; MARGIN: 3px 0px 3px 10px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: ; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_thumb.png" width="600" height="290" />
          </a>
        </p>
        <p align="justify">
The first picture here shows all key pieces except the <em>Supervisor</em> that I’ll
introduce later. At the core we have a <em>Scheduler</em> that manages a simple state
machine made up of <em>Jobs</em> and those jobs have <em>Steps</em>. The steps may
have a notion of interdependency or may be completely parallelizable. There is a <em>Job
Store</em> that holds jobs and steps and there are <em>Agents</em> that execute operations
on some resource.  Each <em>Agent</em> is (usually) fronted by a queue and the <em>Scheduler</em> has
a queue (or service endpoint) through which it receives reply messages from the <em>Agents</em>.
</p>
        <p align="justify">
Steps are recorded in a durable storage table of some sort that has at least the following
fields: <em>Current State</em> (say: Disabled, Active), <em>Desired State</em> (say:
Disabled, Active), <em>LockedUntil</em> (Date/Time value), and <em>Actor</em> plus
any step specific information you want to store and eventually submit with the job
to the step agent.
</p>
        <h3>When Things Go Right
</h3>
        <p>
The initial flow is as follows:
</p>
        <blockquote>
          <p>
            <strong>(1)a</strong> – Submit a new job into the Scheduler (and wait) 
<br /><strong>(2)a</strong> – The Scheduler creates a new job and steps with an initial
current state (<em>‘Disabled’</em>) in the job store  
<br /><strong>(2)b</strong> – The Scheduler sets ‘desired state’ of the job and of all schedulable
steps (dependencies?) to the target state (<em>‘Active’</em>) and sets the ‘locked
until’ timeout of the step to a value in the near future, e.g. ‘Now’ + 2 minutes. 
<br /><strong>(1)b</strong> – Job submission request unblocks and returns
</p>
        </blockquote>
        <p align="justify">
If all went well, we now have a job record and, here in this example, two step records
in our store. They have a current state of <em>‘Disabled’</em> and a desired state
of <em>‘Active’</em>. If things didn’t go well, we’d have incomplete or partially
wedged records or nothing in the job store, at all. The client would also know about
it since we’ve held on to the reply until we have everything done – so the client
is encouraged to retry. If we have nothing in the store and the client doesn’t retry
– well, then the job probably wasn’t all that important, after all. But if we have
at least a job record, we can make it all right later. We’re optimists, though; let’s
assume it all went well.
</p>
        <p align="justify">
For the next steps we assume that there’s a notion of dependencies between the steps
and the second steps depends on the first. If that were not the case, the two actions
would just be happening in parallel.
</p>
        <blockquote>
          <p>
            <strong>(3)</strong> – Place a step message into the queue for the actor for the first
step; Agent 1 in this case. The message contains all the information about the step,
including the current and desired state and also the <em>LockedUntil</em> that puts
an ultimatum on the activity. The message may further contain an action indicator
or arguments that are taken from the step record. 
<br /><strong>(4)</strong> – After the agent has done the work, it places a completion record
into the reply queue of the Scheduler. 
<br /><strong>(5)</strong> – The Scheduler records the step as complete by setting the current
state from ‘Disabled’ to ‘Active’; as a result the desired and the current state are
now equal. 
<br /><strong>(6)</strong> – The Scheduler sets the next step’s desired state to the target
state (<em>‘Active’</em>) and sets the <em>LockedUntil</em> timeout of the step to
a value in the near future, e.g. ‘Now’ + 1 minute. The lock timeout value is an ultimatum
for when the operation is expected to be complete and reported back as being complete
in a worst-case success case. The actual value therefore depends on the common latency
of operations in the system. If operations usually complete in milliseconds and at
worst within a second, the lock timeout can be short – but not too short. We’ll discuss
this  value in more detail a bit later. 
<br /><strong>(7)</strong>, <strong>(8)</strong>, <strong>(9)</strong> are equivalent to <strong>(3)</strong>, <strong>(4)</strong>, <strong>(5)</strong>.
</p>
        </blockquote>
        <p align="justify">
Once the last step’s current state is equal to the current state, the job’s current
state gets set to the desired state and we’re done. So that was the “99% of the time”
happy path.
</p>
        <p>
          <a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_4.png">
            <img style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; MARGIN: 3px 0px 3px 10px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: ; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_thumb_1.png" width="591" height="286" />
          </a>
        </p>
        <h3>When Things Go Wrong
</h3>
        <p align="justify">
So what happens when anything goes wrong? Remember the principle <strong>‘all errors
are transient’</strong>. What we do in the error case – anywhere – is to log the error
condition and then promptly drop everything and simply hope that time, a change in
system conditions, human or divine intervention, or – at worst – a patch will heal
matters. That’s what the second principle <strong>‘the system is perfect’<em> </em></strong>is
about; the system obviously isn’t really perfect, but if we construct it in a way
that we can either wait for it to return from a wedged state into a functional state
or where we enable someone to go in and apply a fix for a blocking bug while preserving
the system state, we can consider the system ‘perfect’ in the sense that pretty much
any conceivable job that’s already in the system can be driven to completion.
</p>
        <p align="justify">
In the second picture, we have Agent 2 blowing up as it is processing the step it
got handed in <strong>(7)</strong>. If the agent just can’t get its work done since
some external dependency isn’t available – maybe a database can’t be reached or a
server it’s talking to spews out ‘server too busy’ errors – it may be able to back
off for a moment and retry. However, it must not retry past the <em>LockedUntil</em> ultimatum
that’s in the step record. When things fail and the agent is still breathing, it may,
as a matter of courtesy, notify the scheduler of the fact and report that the step
was completed with no result, i.e. the desired state and the achieved state don’t
match. That notification may also include diagnostic information. Once the <em>LockedUntil</em> ultimatum
has passed, the Agent no longer owns the job and must drop it. It must even not report
failure state back to the Scheduler past that point. 
</p>
        <p align="justify">
If the agent keels over and dies as it is processing the step (or right before or
right after), it is obviously no longer in a position to let the scheduler know about
its fate. Thus, there won’t be any message flowing back to the scheduler and the job
is stalled. But we expect that. In fact, we’re ok with any failure anywhere in the
system. We could lose or fumble a queue message, we could get a duplicate message,
we could have the scheduler die a fiery death (or just being recycled for patching
at some unfortunate moment) – all of those conditions are fine since we’ve brought
the doctor on board with us: the <em>Supervisor.</em> 
</p>
        <p align="justify">
          <a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_6.png">
            <img style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; MARGIN: 3px 10px 3px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: ; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_thumb_2.png" width="558" height="297" />
          </a>
        </p>
        <h3>The Supervisor
</h3>
        <p>
The Supervisor is a schedule driven process (or thread) of which one or a few instances
may run occasionally. The frequency depends on much on the average duration of operations
and the expected overall latency for completion of jobs. 
</p>
        <p>
The Supervisor’s job is to recover steps or jobs that have failed – and we’re assuming
that failures are due to some transient condition. So if the system would expect a
transient resource failure condition that prevented a job from completing just a second
ago to be healed two seconds later, it’d depend on the kind of system and resource
whether that’d be a good strategy.  What’s described here is a pattern, not a
solution, so it depends on the concrete scenario to get the  timing right for
when to try operations again once they fail.
</p>
        <p>
This desired back-off time manifests in the <em>LockedUntil</em> value.  When
a step gets scheduled, the <em>Scheduler</em> needs to state how long it is willing
to wait for that step to complete; this includes some back-off time padding. Once
that ultimatum has passed and the step is still in an inconsistent state (desired
state doesn’t equal the current state)  the <em>Supervisor</em> can pick it up
at any time and schedule it.
</p>
        <blockquote>
          <p>
            <strong>(1)</strong> – Supervisor queries the job store for any inconsistent steps
whose <em>LockedUntil</em> value has expired. 
<br /><strong>(2) – </strong>The Supervisor schedules the step again by setting the <em>LockedUntil </em>value
to a new timeout and submitting the step into the target actor’s queue 
<br /><strong>(3)</strong> – Once the step succeeds, the step is reported as complete on
the regular path back to the <em>Scheduler</em>  where it completes normally
as in steps <strong>(8)</strong>, <strong>(9)</strong> from the happy-path scenario
above. If it fails, we simply drop it again. For failures that allow reporting an
error back to the <em>Scheduler</em> it may make sense to introduce an error counter
that round-trips with the step so that the system could detect poisonous steps that
fail ‘forever’ and have the <em>Supervisor</em> ignore those after some threshold.
</p>
        </blockquote>
        <p>
The Supervisor can pursue a range of strategies for recovery. It can just take a look
at individual steps and recover them by rescheduling them – assuming the steps are
implemented as idempotent operations. If it were a bit cleverer, it may consider error
information that a cooperative (and breathing) agent has submitted back to the Scheduler
and even go as far as to fire an alert to an operator if the error condition were
to require intervention and then take the step out of the loop by marking it and setting
the <em>LockedUntil</em> value to some longer timeout so it’s taken out of the loop
and someone can take a look. 
</p>
        <p>
At the job-scope, the Supervisor may want to perform recovery such that it first schedules
all previously executed steps to revert back to the initial state by performing compensation
work (all resources that got set to active are getting disabled again here in our
example) and then scheduling another attempt at getting to the desired state. 
</p>
        <p>
In step <strong>(2)b</strong> up above, we’ve been logging current and desired state
at the job-scope and with that we can also always find inconsistent jobs where all
steps are consistent and wouldn’t show up in the step-level recovery query. That situation
can occur if the <em>Scheduler</em> were to crash between logging one step as complete
and scheduling the next step. If we find inconsistent jobs with all-consistent steps,
we just need to reschedule the next step in the dependency sequence whose desired
state isn’t matching the desired state of the overall job.
</p>
        <p>
To be thorough, we could now take a look at all the places where things can go wrong
in the system. I expect that survey to yield that at as long we can successfully get
past step <strong>(2)b </strong>from the first diagram, the <em>Supervisor</em> is
always in a position to either detect that a job isn’t making progress and help with
recovery or can at least call for help. The system always knows what its current <strong>intent</strong> is,
i.e. which state transitions it wants to drive, and never forgets about that intent
since that intent is logged in the job store at all times and all progress against
that intent is logged as well.  The submission request <strong>(1)</strong> depends
on the outcome of <strong>(2)a/b </strong>to guard against failures while putting
a job and its steps into the system so that a client can take corrective action. In
fact, once the job record is marked as inconsistent in step <strong>(2)b</strong>,
the scheduler could already report success back to the submitting party even before
the first step is scheduled, because the <em>Supervisor</em> would pick up that inconsistency
eventually.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=83f937f7-b838-43d0-ad61-74605eceafa2" />
      </body>
      <title>Cloud Architecture: The Scheduler-Agent-Supervisor Pattern</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,83f937f7-b838-43d0-ad61-74605eceafa2.aspx</guid>
      <link>http://vasters.com/clemensv/2010/09/28/Cloud+Architecture+The+SchedulerAgentSupervisor+Pattern.aspx</link>
      <pubDate>Tue, 28 Sep 2010 01:55:18 GMT</pubDate>
      <description>&lt;p align=justify&gt;
As our team was starting to transform our parts of the Azure Services Platform from
a CTP ‘labs’ service exploring features into a full-on commercial service, it started
to dawn on us that we had set ourselves up for writing a bunch of ‘enterprise apps’.
The shiny parts of Service Bus and Access Control that we parade around are all about
user-facing features, but if I look back at the work we had to go from a toy service
to a commercial offering, I’d guess that 80%-90% of the effort went into aspects like
infrastructure, deployment, upgradeability, billing, provisioning, throttling, quotas,
security hardening, and service optimization. The lesson there was: when you’re boarding
the train to shipping a V1, you don’t load new features on that train –&amp;nbsp; you
rather throw some off. 
&lt;/p&gt;
&lt;p align=justify&gt;
The most interesting challenge for these infrastructure apps sitting on the backend
was that we didn’t have much solid ground to stand on. Remember – these were very
early days, so we couldn’t use SQL Azure since the folks over in SQL were on a pretty
heroic schedule themselves and didn’t want to take on any external dependencies even
from close friends. We also couldn’t use any of the capabilities of our own bits because
building infrastructure for your features on your features would just be plain dumb.
And while we could use capabilities of the Windows Azure platform we were building
on, a lot of those parts still had rough edges as those folks were going through a
lot of the same that we went through. In those days, the table store would be very
moody, the queue store would sometimes swallow or duplicate messages, the Azure fabric
controller would occasionally go around and kill things. All normal –&amp;nbsp; bugs.
&lt;/p&gt;
&lt;p align=justify&gt;
So under those circumstances we had to figure out the architecture for some subsystems
where we need to do a set of coordinated action across a distributed set of resources
– a distributed transaction or saga of sorts. The architecture had a few simple goals:
when we get an activation request, we must not fumble that request under any circumstance,
we must run the job to completion for all resources and, at the same time, we need
to minimize any potential for required operator intervention, i.e. if something goes
wrong, the system better knows how to deal with it – at best it should self-heal. 
&lt;/p&gt;
&lt;p align=justify&gt;
My solution to that puzzle is a pattern I call “Scheduler-Agent-Supervisor Pattern”
or, short, “Supervisor Pattern”. We keep finding applications for this pattern in
different places, so I think it’s worth writing about it in generic terms – even without
going into the details of our system.
&lt;/p&gt;
&lt;p align=justify&gt;
The pattern foots on two seemingly odd and very related assumptions: &lt;em&gt;‘&lt;/em&gt;&lt;strong&gt;&lt;em&gt;the
system is perfect’&lt;/em&gt; &lt;/strong&gt;and&lt;strong&gt; &lt;em&gt;‘all error conditions are transient’&lt;/em&gt;.&lt;/strong&gt; As
a consequence, the architecture has some character traits of a toddler. It’s generally
happily optimistic and gets very grumpy, very quickly when things go wrong – to the
point that it will simply drop everything and run away screaming. It’s very precisely
like that, in fact.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_2.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; MARGIN: 3px 0px 3px 10px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: ; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_thumb.png" width=600 height=290&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p align=justify&gt;
The first picture here shows all key pieces except the &lt;em&gt;Supervisor&lt;/em&gt; that I’ll
introduce later. At the core we have a &lt;em&gt;Scheduler&lt;/em&gt; that manages a simple state
machine made up of &lt;em&gt;Jobs&lt;/em&gt; and those jobs have &lt;em&gt;Steps&lt;/em&gt;. The steps may
have a notion of interdependency or may be completely parallelizable. There is a &lt;em&gt;Job
Store&lt;/em&gt; that holds jobs and steps and there are &lt;em&gt;Agents&lt;/em&gt; that execute operations
on some resource.&amp;nbsp; Each &lt;em&gt;Agent&lt;/em&gt; is (usually) fronted by a queue and the &lt;em&gt;Scheduler&lt;/em&gt; has
a queue (or service endpoint) through which it receives reply messages from the &lt;em&gt;Agents&lt;/em&gt;.
&lt;/p&gt;
&lt;p align=justify&gt;
Steps are recorded in a durable storage table of some sort that has at least the following
fields: &lt;em&gt;Current State&lt;/em&gt; (say: Disabled, Active), &lt;em&gt;Desired State&lt;/em&gt; (say:
Disabled, Active), &lt;em&gt;LockedUntil&lt;/em&gt; (Date/Time value), and &lt;em&gt;Actor&lt;/em&gt; plus
any step specific information you want to store and eventually submit with the job
to the step agent.
&lt;/p&gt;
&lt;h3&gt;When Things Go Right
&lt;/h3&gt;
&lt;p&gt;
The initial flow is as follows:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;(1)a&lt;/strong&gt; – Submit a new job into the Scheduler (and wait) 
&lt;br&gt;
&lt;strong&gt;(2)a&lt;/strong&gt; – The Scheduler creates a new job and steps with an initial
current state (&lt;em&gt;‘Disabled’&lt;/em&gt;) in the job store&amp;nbsp; 
&lt;br&gt;
&lt;strong&gt;(2)b&lt;/strong&gt; – The Scheduler sets ‘desired state’ of the job and of all schedulable
steps (dependencies?) to the target state (&lt;em&gt;‘Active’&lt;/em&gt;) and sets the ‘locked
until’ timeout of the step to a value in the near future, e.g. ‘Now’ + 2 minutes. 
&lt;br&gt;
&lt;strong&gt;(1)b&lt;/strong&gt; – Job submission request unblocks and returns
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p align=justify&gt;
If all went well, we now have a job record and, here in this example, two step records
in our store. They have a current state of &lt;em&gt;‘Disabled’&lt;/em&gt; and a desired state
of &lt;em&gt;‘Active’&lt;/em&gt;. If things didn’t go well, we’d have incomplete or partially
wedged records or nothing in the job store, at all. The client would also know about
it since we’ve held on to the reply until we have everything done – so the client
is encouraged to retry. If we have nothing in the store and the client doesn’t retry
– well, then the job probably wasn’t all that important, after all. But if we have
at least a job record, we can make it all right later. We’re optimists, though; let’s
assume it all went well.
&lt;/p&gt;
&lt;p align=justify&gt;
For the next steps we assume that there’s a notion of dependencies between the steps
and the second steps depends on the first. If that were not the case, the two actions
would just be happening in parallel.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;(3)&lt;/strong&gt; – Place a step message into the queue for the actor for the first
step; Agent 1 in this case. The message contains all the information about the step,
including the current and desired state and also the &lt;em&gt;LockedUntil&lt;/em&gt; that puts
an ultimatum on the activity. The message may further contain an action indicator
or arguments that are taken from the step record. 
&lt;br&gt;
&lt;strong&gt;(4)&lt;/strong&gt; – After the agent has done the work, it places a completion record
into the reply queue of the Scheduler. 
&lt;br&gt;
&lt;strong&gt;(5)&lt;/strong&gt; – The Scheduler records the step as complete by setting the current
state from ‘Disabled’ to ‘Active’; as a result the desired and the current state are
now equal. 
&lt;br&gt;
&lt;strong&gt;(6)&lt;/strong&gt; – The Scheduler sets the next step’s desired state to the target
state (&lt;em&gt;‘Active’&lt;/em&gt;) and sets the &lt;em&gt;LockedUntil&lt;/em&gt; timeout of the step to
a value in the near future, e.g. ‘Now’ + 1 minute. The lock timeout value is an ultimatum
for when the operation is expected to be complete and reported back as being complete
in a worst-case success case. The actual value therefore depends on the common latency
of operations in the system. If operations usually complete in milliseconds and at
worst within a second, the lock timeout can be short – but not too short. We’ll discuss
this&amp;nbsp; value in more detail a bit later. 
&lt;br&gt;
&lt;strong&gt;(7)&lt;/strong&gt;, &lt;strong&gt;(8)&lt;/strong&gt;, &lt;strong&gt;(9)&lt;/strong&gt; are equivalent to &lt;strong&gt;(3)&lt;/strong&gt;, &lt;strong&gt;(4)&lt;/strong&gt;, &lt;strong&gt;(5)&lt;/strong&gt;.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p align=justify&gt;
Once the last step’s current state is equal to the current state, the job’s current
state gets set to the desired state and we’re done. So that was the “99% of the time”
happy path.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_4.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; MARGIN: 3px 0px 3px 10px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: ; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_thumb_1.png" width=591 height=286&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h3&gt;When Things Go Wrong
&lt;/h3&gt;
&lt;p align=justify&gt;
So what happens when anything goes wrong? Remember the principle &lt;strong&gt;‘all errors
are transient’&lt;/strong&gt;. What we do in the error case – anywhere – is to log the error
condition and then promptly drop everything and simply hope that time, a change in
system conditions, human or divine intervention, or – at worst – a patch will heal
matters. That’s what the second principle &lt;strong&gt;‘the system is perfect’&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;is
about; the system obviously isn’t really perfect, but if we construct it in a way
that we can either wait for it to return from a wedged state into a functional state
or where we enable someone to go in and apply a fix for a blocking bug while preserving
the system state, we can consider the system ‘perfect’ in the sense that pretty much
any conceivable job that’s already in the system can be driven to completion.
&lt;/p&gt;
&lt;p align=justify&gt;
In the second picture, we have Agent 2 blowing up as it is processing the step it
got handed in &lt;strong&gt;(7)&lt;/strong&gt;. If the agent just can’t get its work done since
some external dependency isn’t available – maybe a database can’t be reached or a
server it’s talking to spews out ‘server too busy’ errors – it may be able to back
off for a moment and retry. However, it must not retry past the &lt;em&gt;LockedUntil&lt;/em&gt; ultimatum
that’s in the step record. When things fail and the agent is still breathing, it may,
as a matter of courtesy, notify the scheduler of the fact and report that the step
was completed with no result, i.e. the desired state and the achieved state don’t
match. That notification may also include diagnostic information. Once the &lt;em&gt;LockedUntil&lt;/em&gt; ultimatum
has passed, the Agent no longer owns the job and must drop it. It must even not report
failure state back to the Scheduler past that point. 
&lt;/p&gt;
&lt;p align=justify&gt;
If the agent keels over and dies as it is processing the step (or right before or
right after), it is obviously no longer in a position to let the scheduler know about
its fate. Thus, there won’t be any message flowing back to the scheduler and the job
is stalled. But we expect that. In fact, we’re ok with any failure anywhere in the
system. We could lose or fumble a queue message, we could get a duplicate message,
we could have the scheduler die a fiery death (or just being recycled for patching
at some unfortunate moment) – all of those conditions are fine since we’ve brought
the doctor on board with us: the &lt;em&gt;Supervisor.&lt;/em&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p align=justify&gt;
&lt;a href="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_6.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-RIGHT-WIDTH: 0px; MARGIN: 3px 10px 3px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: ; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px" title=image border=0 alt=image src="http://vasters.com/clemensv/content/binary/Windows-Live-Writer/d4c99e27e28d_1248C/image_thumb_2.png" width=558 height=297&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h3&gt;The Supervisor
&lt;/h3&gt;
&lt;p&gt;
The Supervisor is a schedule driven process (or thread) of which one or a few instances
may run occasionally. The frequency depends on much on the average duration of operations
and the expected overall latency for completion of jobs. 
&lt;/p&gt;
&lt;p&gt;
The Supervisor’s job is to recover steps or jobs that have failed – and we’re assuming
that failures are due to some transient condition. So if the system would expect a
transient resource failure condition that prevented a job from completing just a second
ago to be healed two seconds later, it’d depend on the kind of system and resource
whether that’d be a good strategy.&amp;nbsp; What’s described here is a pattern, not a
solution, so it depends on the concrete scenario to get the&amp;nbsp; timing right for
when to try operations again once they fail.
&lt;/p&gt;
&lt;p&gt;
This desired back-off time manifests in the &lt;em&gt;LockedUntil&lt;/em&gt; value.&amp;nbsp; When
a step gets scheduled, the &lt;em&gt;Scheduler&lt;/em&gt; needs to state how long it is willing
to wait for that step to complete; this includes some back-off time padding. Once
that ultimatum has passed and the step is still in an inconsistent state (desired
state doesn’t equal the current state)&amp;nbsp; the &lt;em&gt;Supervisor&lt;/em&gt; can pick it up
at any time and schedule it.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;(1)&lt;/strong&gt; – Supervisor queries the job store for any inconsistent steps
whose &lt;em&gt;LockedUntil&lt;/em&gt; value has expired. 
&lt;br&gt;
&lt;strong&gt;(2) – &lt;/strong&gt;The Supervisor schedules the step again by setting the &lt;em&gt;LockedUntil &lt;/em&gt;value
to a new timeout and submitting the step into the target actor’s queue 
&lt;br&gt;
&lt;strong&gt;(3)&lt;/strong&gt; – Once the step succeeds, the step is reported as complete on
the regular path back to the &lt;em&gt;Scheduler&lt;/em&gt;&amp;nbsp; where it completes normally
as in steps &lt;strong&gt;(8)&lt;/strong&gt;, &lt;strong&gt;(9)&lt;/strong&gt; from the happy-path scenario
above. If it fails, we simply drop it again. For failures that allow reporting an
error back to the &lt;em&gt;Scheduler&lt;/em&gt; it may make sense to introduce an error counter
that round-trips with the step so that the system could detect poisonous steps that
fail ‘forever’ and have the &lt;em&gt;Supervisor&lt;/em&gt; ignore those after some threshold.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The Supervisor can pursue a range of strategies for recovery. It can just take a look
at individual steps and recover them by rescheduling them – assuming the steps are
implemented as idempotent operations. If it were a bit cleverer, it may consider error
information that a cooperative (and breathing) agent has submitted back to the Scheduler
and even go as far as to fire an alert to an operator if the error condition were
to require intervention and then take the step out of the loop by marking it and setting
the &lt;em&gt;LockedUntil&lt;/em&gt; value to some longer timeout so it’s taken out of the loop
and someone can take a look. 
&lt;/p&gt;
&lt;p&gt;
At the job-scope, the Supervisor may want to perform recovery such that it first schedules
all previously executed steps to revert back to the initial state by performing compensation
work (all resources that got set to active are getting disabled again here in our
example) and then scheduling another attempt at getting to the desired state. 
&lt;/p&gt;
&lt;p&gt;
In step &lt;strong&gt;(2)b&lt;/strong&gt; up above, we’ve been logging current and desired state
at the job-scope and with that we can also always find inconsistent jobs where all
steps are consistent and wouldn’t show up in the step-level recovery query. That situation
can occur if the &lt;em&gt;Scheduler&lt;/em&gt; were to crash between logging one step as complete
and scheduling the next step. If we find inconsistent jobs with all-consistent steps,
we just need to reschedule the next step in the dependency sequence whose desired
state isn’t matching the desired state of the overall job.
&lt;/p&gt;
&lt;p&gt;
To be thorough, we could now take a look at all the places where things can go wrong
in the system. I expect that survey to yield that at as long we can successfully get
past step &lt;strong&gt;(2)b &lt;/strong&gt;from the first diagram, the &lt;em&gt;Supervisor&lt;/em&gt; is
always in a position to either detect that a job isn’t making progress and help with
recovery or can at least call for help. The system always knows what its current &lt;strong&gt;intent&lt;/strong&gt; is,
i.e. which state transitions it wants to drive, and never forgets about that intent
since that intent is logged in the job store at all times and all progress against
that intent is logged as well.&amp;nbsp; The submission request &lt;strong&gt;(1)&lt;/strong&gt; depends
on the outcome of &lt;strong&gt;(2)a/b &lt;/strong&gt;to guard against failures while putting
a job and its steps into the system so that a client can take corrective action. In
fact, once the job record is marked as inconsistent in step &lt;strong&gt;(2)b&lt;/strong&gt;,
the scheduler could already report success back to the submitting party even before
the first step is scheduled, because the &lt;em&gt;Supervisor&lt;/em&gt; would pick up that inconsistency
eventually.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=83f937f7-b838-43d0-ad61-74605eceafa2" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,83f937f7-b838-43d0-ad61-74605eceafa2.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Azure</category>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=a14d84f7-0d07-49da-a5d8-35088052c3e5</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,a14d84f7-0d07-49da-a5d8-35088052c3e5.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,a14d84f7-0d07-49da-a5d8-35088052c3e5.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=a14d84f7-0d07-49da-a5d8-35088052c3e5</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In case you need a refresher or update about the things me and our team work on at
Microsoft, <a href="http://www.msteched.com/2010/Australia/COS230">go here</a> for
a very recent and very good presentation by my PM colleague <a href="http://twitter.com/mmyslin">Maggie
Myslinska</a> from TechEd Australia 2010 about Windows Azure AppFabric with Service
Bus demos and a demo of the new Access Control V2 CTP
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=a14d84f7-0d07-49da-a5d8-35088052c3e5" />
      </body>
      <title>Windows Azure AppFabric Overview session from TechEd Australia 2010 </title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,a14d84f7-0d07-49da-a5d8-35088052c3e5.aspx</guid>
      <link>http://vasters.com/clemensv/2010/09/09/Windows+Azure+AppFabric+Overview+Session+From+TechEd+Australia+2010.aspx</link>
      <pubDate>Thu, 09 Sep 2010 01:08:52 GMT</pubDate>
      <description>&lt;p&gt;
In case you need a refresher or update about the things me and our team work on at
Microsoft, &lt;a href="http://www.msteched.com/2010/Australia/COS230"&gt;go here&lt;/a&gt; for
a very recent and very good presentation by my PM colleague &lt;a href="http://twitter.com/mmyslin"&gt;Maggie
Myslinska&lt;/a&gt; from TechEd Australia 2010 about Windows Azure AppFabric with Service
Bus demos and a demo of the new Access Control V2 CTP
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=a14d84f7-0d07-49da-a5d8-35088052c3e5" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,a14d84f7-0d07-49da-a5d8-35088052c3e5.aspx</comments>
      <category>AppFabric</category>
      <category>Architecture/SOA</category>
      <category>Azure</category>
      <category>Technology</category>
      <category>Technology/ISB</category>
      <category>Technology/WCF</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=e59f4a38-8e07-401a-b291-3ab4a561a2ae</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,e59f4a38-8e07-401a-b291-3ab4a561a2ae.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,e59f4a38-8e07-401a-b291-3ab4a561a2ae.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=e59f4a38-8e07-401a-b291-3ab4a561a2ae</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Earlier today I hopefully gave a somewhat reasonable, simple answer to the question
"<a href="http://vasters.com/clemensv/PermaLink,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx">What
is a Claim?</a>" Let's try the same with "Token":
</p>
        <p>
In the WS-* security world, "Token" is really just a another name the security
geniuses decided to use for "Handy package for all sorts of security
stuff". The most popular type of token is the <a href="http://en.wikipedia.org/wiki/SAML">SAML</a> (just
say "samel") token. If the ladies and gentlemen designing and writing security platform
infrastructure and frameworks are doing a good job you might want to know about the
existence of such a thing, but otherwise be blissfully ignorant of all the gory details. 
</p>
        <p>
Tokens are meant to be a thing that you need to know about in much the same way you
need to know about ... ummm... rebate coupons you can cut out of your local newspaper
or all those funny books that you get in the mail. I have really no idea how the accounting
works behind the scenes between the manufacturers and the stores, but it really doesn't
interest me much, either. What matters to me is that we get $4 off that jumbo pack
of diapers and we go through a lot of those these days with a 9 month old baby here
at home. We cut out the coupon, present it at the store, four bucks saved. Works for
me.
</p>
        <p>
A token is the same kind of deal. You go to some (security) service, get a token,
and present that token to some other service. The other service takes a good look
at the token and figures whether it 'trusts' the token issuer and might then
do some further inspection; if all is well you get four bucks off. Or you get
to do the thing you want to do at the service. The latter is more likely, but I liked
the idea for a moment.
</p>
        <p>
Remember when I mentioned the surprising fact that <strong>people lie</strong> from
time to time when I wrote about <a href="http://vasters.com/clemensv/PermaLink,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx">claims</a>?
Well, that's where tokens come in. The security stuff in a token is there to keep
people honest and to make '<a href="http://dictionary.reference.com/search?q=assertion">assertions</a>'
about claims. The security dudes and dudettes will say "Err, that's not the whole
story", but for me it's good enough. It's actually pretty common (that'll be
their objection) that there are tokens that don't carry any claims and where
the security service effectively says "whoever brings this token is a fine person;
they are ok to get in". It's like having a really close buddy relationship with the
boss of the nightclub when you are having troubles with the monsters guarding the
door. I'm getting a bit ahead of myself here, though.
</p>
        <p>
In the post about claims I claimed that "I am authorized to approve corporate
acquisitions with a transaction volume of up to $5Bln". That's a pretty obvious lie.
If there was such a thing as a one-click shopping button for companies on some Microsoft
Intranet site (there isn't, don't get any ideas) and I were to push it, I surely
should not be authorized to execute the transaction. The imaginary "just
one click and you own Xigg" button would surely have some sort of authorization
mechanism on it. 
</p>
        <p>
I don't know what Xigg is assumed to be worth these days, but there is actually be
a second authorization gate to check. I might indeed be authorized to do one-click
shopping for corporate acquisitions, but even with my made-up $5Bln limit claim, Xigg
may just be worth more that I'm claiming I'm authorized to approve. I digress.
</p>
        <p>
How would the one-click-merger-approval service be secured? It would expect some sort
of token that absolutely, positively asserts that my claim "I am authorized to approve corporate
acquisitions with a transaction volume of up to $5Bln" is truthful and the one-click-merger-approval
service would have to absolutely trust the security service that is making that
assertion. The resulting token that I'm getting from the security service would contain
the claim as an attribute of the assertion and that assertion would be signed and
encrypted in mysterious (for me) yet very secure and interoperable ways, so that I
can't tamper with it as much as I look at the token while having it in hands.
</p>
        <p>
The service receiving the token is the only one able to crack the token (I'll get
to that point in a later post) and look at its internals and the asserted attributes.
So what if I were indeed authorized to spend a bit of Microsoft's reserves
and I were trying to acquire Xigg at the touch of a button and, for some reason I
wouldn't understand, the valuation were outside my acquisition limit? That's
the service's job. It'd look at my claim, understand that I can't spend more than
$5Bln and say "nope!" - and it would likely send email to SteveB under the covers.
Trouble.
</p>
        <p>
Bottom line: For a client application, a token is a collection of opaque (and
mysterious) security stuff. The token may contain an assertion (saying "yep,
that's actually true") about a claim or a set of claims that I am making. I shouldn't
have to care about the further details unless I'm writing a service and I'm interested
in some deeper inspection of the claims that have been asserted. I will
get to that.
</p>
        <p>
Before that, I notice that I talked quite a bit about some sort of "security service"
here. Next post...
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e59f4a38-8e07-401a-b291-3ab4a561a2ae" />
      </body>
      <title>What is a Token?</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,e59f4a38-8e07-401a-b291-3ab4a561a2ae.aspx</guid>
      <link>http://vasters.com/clemensv/2008/04/03/What+Is+A+Token.aspx</link>
      <pubDate>Thu, 03 Apr 2008 06:10:36 GMT</pubDate>
      <description>&lt;p&gt;
Earlier today I hopefully gave a somewhat reasonable, simple answer to the question
"&lt;a href="http://vasters.com/clemensv/PermaLink,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx"&gt;What
is a Claim?&lt;/a&gt;" Let's try the same with "Token":
&lt;/p&gt;
&lt;p&gt;
In the WS-* security world, "Token" is really just a&amp;nbsp;another name the security
geniuses&amp;nbsp;decided to use&amp;nbsp;for "Handy package&amp;nbsp;for all sorts of security
stuff". The most popular type of token is the &lt;a href="http://en.wikipedia.org/wiki/SAML"&gt;SAML&lt;/a&gt; (just
say "samel") token. If the ladies and gentlemen designing and writing security platform
infrastructure and frameworks are doing a good job you might want to know about the
existence of such a thing, but otherwise be blissfully ignorant of all the gory details. 
&lt;/p&gt;
&lt;p&gt;
Tokens are meant to be a thing that you need to know about in much the same way you
need to know about ... ummm... rebate coupons you can cut out of your local newspaper
or all those funny books that you get in the mail. I have really no idea how the accounting
works behind the scenes between the manufacturers and the stores, but it really doesn't
interest me much, either. What matters to me is that we get $4 off that jumbo pack
of diapers and we go through a lot of those these days with a 9 month old baby here
at home. We cut out the coupon, present it at the store, four bucks saved. Works for
me.
&lt;/p&gt;
&lt;p&gt;
A token is the same kind of deal. You go to some (security) service, get a token,
and present that token to some other service. The other service takes a good look
at the token and figures whether it 'trusts' the token issuer and&amp;nbsp;might then
do some further inspection; if all is well you get four bucks off. Or&amp;nbsp;you get
to do the thing you want to do at the service. The latter is more likely, but I liked
the idea for a moment.
&lt;/p&gt;
&lt;p&gt;
Remember when I mentioned the surprising fact that &lt;strong&gt;people lie&lt;/strong&gt; from
time to time when I wrote about &lt;a href="http://vasters.com/clemensv/PermaLink,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx"&gt;claims&lt;/a&gt;?
Well, that's where tokens come in. The security stuff in a token is there to keep
people honest and to make '&lt;a href="http://dictionary.reference.com/search?q=assertion"&gt;assertions&lt;/a&gt;'
about claims. The security dudes and dudettes will say "Err, that's not the whole
story", but for me it's good enough.&amp;nbsp;It's actually pretty common (that'll be
their objection) that there are&amp;nbsp;tokens that don't carry any claims and where
the security service effectively says "whoever brings this token is a fine person;
they are ok to get in". It's like having a really close buddy relationship with the
boss of the nightclub when you are having troubles with the monsters guarding the
door. I'm getting a bit ahead of myself here, though.
&lt;/p&gt;
&lt;p&gt;
In the post about claims I claimed that "I am authorized to approve&amp;nbsp;corporate
acquisitions with a transaction volume of up to $5Bln". That's a pretty obvious lie.
If there was such a thing as a one-click shopping button for companies on some Microsoft
Intranet site (there isn't, don't get any ideas) and I were to push it, I&amp;nbsp;surely
should&amp;nbsp;not be authorized to execute the transaction.&amp;nbsp;The imaginary "just
one click and you&amp;nbsp;own Xigg" button would surely have some sort of authorization
mechanism on it. 
&lt;/p&gt;
&lt;p&gt;
I don't know what Xigg is assumed to be worth these days, but there is actually be
a second authorization gate to check. I might indeed be authorized to do one-click
shopping for corporate acquisitions, but even with my made-up $5Bln limit claim, Xigg
may just be worth more that I'm claiming I'm authorized to approve. I digress.
&lt;/p&gt;
&lt;p&gt;
How would the one-click-merger-approval service be secured? It would expect some sort
of token that absolutely, positively asserts that my claim "I am authorized to approve&amp;nbsp;corporate
acquisitions with a transaction volume of up to $5Bln" is truthful and&amp;nbsp;the one-click-merger-approval
service would have to absolutely trust the security service that&amp;nbsp;is making that
assertion. The resulting token that I'm getting from the security service would contain
the claim as an attribute of the assertion and that assertion would be signed and
encrypted in mysterious (for me) yet very secure and interoperable ways, so that I
can't tamper with it as much as I look at the token while having it in hands.
&lt;/p&gt;
&lt;p&gt;
The service receiving the token is the only one able to crack the token (I'll get
to that point in a later post) and look at its internals and the asserted attributes.
So what if I were indeed authorized to&amp;nbsp;spend&amp;nbsp;a bit of&amp;nbsp;Microsoft's&amp;nbsp;reserves
and I were trying to acquire Xigg at the touch of a button and, for some reason I
wouldn't understand,&amp;nbsp;the valuation were outside my acquisition limit? That's
the service's job. It'd look at my claim, understand that I can't spend more than
$5Bln and say "nope!" - and it would likely send email to SteveB under the covers.
Trouble.
&lt;/p&gt;
&lt;p&gt;
Bottom line: For a client application,&amp;nbsp;a token is a collection of opaque (and
mysterious) security stuff.&amp;nbsp;The token may contain&amp;nbsp;an assertion (saying "yep,
that's actually true") about a&amp;nbsp;claim or a set of claims that I am making. I shouldn't
have to care about the further details unless I'm writing a service and I'm interested
in some deeper&amp;nbsp;inspection of the claims that have been asserted.&amp;nbsp;I will
get to that.
&lt;/p&gt;
&lt;p&gt;
Before that, I notice that I talked quite a bit about some sort of "security service"
here. Next post...
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e59f4a38-8e07-401a-b291-3ab4a561a2ae" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,e59f4a38-8e07-401a-b291-3ab4a561a2ae.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology/CardSpace</category>
      <category>Technology/WCF</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=6efdfc92-27ac-4d51-8aa1-f187eba098d0</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=6efdfc92-27ac-4d51-8aa1-f187eba098d0</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
If you ask any search engine "What is a Claim?" and you mean the sort of claim used in
the WS-* security space, you'll likely find an answer somewhere, but that answer
is just as likely buried in a sea of complex terminology that is only really comprehensible
if you have already wrapped your head around the details of the WS-* security model.
I would have thought that by now there would be a simple and not too technical explanation
of the concept that's easy to find on the Web, but I haven't really had success finding
one.  
</p>
        <p>
So "What is a Claim?" It's really simple.
</p>
        <p>
A <strong>claim</strong> is just a simple statement like "I am Clemens Vasters", or
"I am over 21 years of age", or "I am a Microsoft employee", or "I work in the Connected
Systems Division", or "I am authorized to approve corporate acquisitions with
a transaction volume of up to $5Bln". A <strong>claim set</strong> is just a bundle
of such claims. 
</p>
        <p>
When I walk up to a service with some client program and want to do something on the
service that requires authorization, the client program sends a claim set
along with the request. For the client to know what claims to send along, the
service lets it know about its requirements in its <strong>policy</strong>. 
</p>
        <p>
When a request comes in, this imaginary (U.S.) service looks at the request
knowing <em>"I'm a service for an online game  promoting alcoholic
beverages!". </em>It then it looks at the claim set, finds the <em>"I am over
21 years of age"</em> claim and thinks <em>"Alright, I think we got that covered"</em>. 
</p>
        <p>
The service didn't really care who was trying to get at the service. And it shouldn't.
To cover the liquor company's legal behind, they only need to know that you are over
21. They don't really need to know (and you probably don't want them to know) who is
talking to them. From the client's perspective that's a good thing, because the
client is now in a position to refuse giving out (m)any clues about the
user's identity and only provide the exact data needed to pass the authorization
gate. Mind that the claim isn't the date of birth for that exact reason. The claim
just says "over 21".
</p>
        <p>
Providing control over what claims are being sent to a service (I'm lumping websites,
SOAP, and REST services all in the same bucket here) is one of the key reasons
why Windows CardSpace exists, by the way. The service asks for a set of claims,
you get to see what is being asked for, and it's ultimately your personal, interactive decision
to provide or refuse to provide that information. 
</p>
        <p>
The only problem with relying on simple statements (claims) of that sort is that <strong>people
lie</strong>. When you go to the <a href="http://www.jackdaniels.com/">Jack Daniel's</a> website,
you are asked to enter your date of birth before you can proceed. In reality, it's
any date you like and an 10-year old kid is easily smart enough to figure that out. 
</p>
        <p>
All that complex security stuff is mostly there to keep people honest. Next time ...
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=6efdfc92-27ac-4d51-8aa1-f187eba098d0" />
      </body>
      <title>What is a Claim?</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx</guid>
      <link>http://vasters.com/clemensv/2008/04/02/What+Is+A+Claim.aspx</link>
      <pubDate>Wed, 02 Apr 2008 20:20:43 GMT</pubDate>
      <description>&lt;p&gt;
If you ask any search engine "What is a Claim?" and you mean the sort of claim used&amp;nbsp;in
the WS-* security space, you'll&amp;nbsp;likely find an answer somewhere, but that answer
is just as likely buried in a sea of complex terminology that is only really comprehensible
if you have already wrapped your head around the details of the WS-* security model.
I would have thought that by now there would be a simple and not too technical explanation
of the concept that's easy to find on the Web, but I haven't really had success finding
one.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
So "What is a Claim?" It's really simple.
&lt;/p&gt;
&lt;p&gt;
A &lt;strong&gt;claim&lt;/strong&gt; is just a simple statement like "I am Clemens Vasters", or
"I am over 21 years of age", or "I am a Microsoft employee", or "I work in the Connected
Systems Division", or "I am authorized to approve&amp;nbsp;corporate acquisitions with
a transaction volume of up to $5Bln". A &lt;strong&gt;claim set&lt;/strong&gt; is just a bundle
of such claims. 
&lt;/p&gt;
&lt;p&gt;
When I walk up to a service with some client program and want to do something on the
service that requires authorization,&amp;nbsp;the client program&amp;nbsp;sends a claim set
along with the request.&amp;nbsp;For the client to know what claims to send along, the
service&amp;nbsp;lets it know about its requirements in&amp;nbsp;its&amp;nbsp;&lt;strong&gt;policy&lt;/strong&gt;. 
&lt;/p&gt;
&lt;p&gt;
When a request comes in, this imaginary (U.S.) service&amp;nbsp;looks at&amp;nbsp;the request
knowing &lt;em&gt;"I'm a&amp;nbsp;service&amp;nbsp;for an online game&amp;nbsp; promoting&amp;nbsp;alcoholic
beverages!". &lt;/em&gt;It then it looks at the claim set,&amp;nbsp;finds the &lt;em&gt;"I am over
21 years of age"&lt;/em&gt; claim and&amp;nbsp;thinks &lt;em&gt;"Alright, I think we got that covered"&lt;/em&gt;. 
&lt;/p&gt;
&lt;p&gt;
The service&amp;nbsp;didn't really care who was trying to get at the service. And it shouldn't.
To cover the liquor company's legal behind, they only need to know that you are over
21. They don't really need to know (and you probably don't want them to know) who&amp;nbsp;is
talking to them.&amp;nbsp;From the client's perspective that's&amp;nbsp;a good thing, because&amp;nbsp;the
client is now in a position to&amp;nbsp;refuse giving out&amp;nbsp;(m)any clues about the
user's identity and only provide the exact data needed&amp;nbsp;to pass the authorization
gate. Mind that the claim isn't the date of birth for that exact reason. The claim
just says "over 21".
&lt;/p&gt;
&lt;p&gt;
Providing control over what claims are being sent to a service (I'm lumping websites,
SOAP, and REST services all in the same bucket here) is&amp;nbsp;one of the&amp;nbsp;key reasons
why Windows CardSpace exists, by the way. The service&amp;nbsp;asks for a set of claims,
you get to&amp;nbsp;see what is being asked for, and it's ultimately your personal, interactive&amp;nbsp;decision
to provide or refuse to provide that information. 
&lt;/p&gt;
&lt;p&gt;
The only problem with relying on simple statements (claims)&amp;nbsp;of that sort is that &lt;strong&gt;people
lie&lt;/strong&gt;.&amp;nbsp;When you go to the &lt;a href="http://www.jackdaniels.com/"&gt;Jack Daniel's&lt;/a&gt; website,
you are asked to enter your date of birth before you can proceed. In reality, it's
any date you like and an 10-year old kid is easily smart enough to figure that out. 
&lt;/p&gt;
&lt;p&gt;
All that complex security stuff is mostly there to keep people honest. Next time ...
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=6efdfc92-27ac-4d51-8aa1-f187eba098d0" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,6efdfc92-27ac-4d51-8aa1-f187eba098d0.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology/CardSpace</category>
      <category>Technology/WCF</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://blogs.thinktecture.com/cweyer/archive/2007/04/27/414819.aspx">Christian
Weyer shows</a> off the few lines of pretty straightforward WCF code &amp; config he
needed to figure out in order to set up a duplex conversation through BizTalk
Services. 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae" />
      </body>
      <title>BizTalk Services: Christian shuttling back and forth on the bus</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae.aspx</guid>
      <link>http://vasters.com/clemensv/2007/04/27/BizTalk+Services+Christian+Shuttling+Back+And+Forth+On+The+Bus.aspx</link>
      <pubDate>Fri, 27 Apr 2007 23:53:15 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://blogs.thinktecture.com/cweyer/archive/2007/04/27/414819.aspx"&gt;Christian
Weyer shows&lt;/a&gt; off the few lines of pretty straightforward WCF code &amp;amp; config&amp;nbsp;he
needed to figure out in order to&amp;nbsp;set up a duplex conversation through BizTalk
Services. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,b2d16e20-c2d6-4a8c-b59a-640cd7dbc0ae.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology/BizTalk</category>
      <category>Technology/WCF</category>
      <category>Technology/Web Services</category>
      <category>Technology/XML</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=d53f0e81-eebb-4327-a92f-2f2ab5fcc602</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,d53f0e81-eebb-4327-a92f-2f2ab5fcc602.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,d53f0e81-eebb-4327-a92f-2f2ab5fcc602.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=d53f0e81-eebb-4327-a92f-2f2ab5fcc602</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Steve has a <a href="http://www.stephenforte.net/owdasblog/PermaLink.aspx?guid=a8de9324-c373-4cab-8e10-4e23251a3fb4">great
analysis </a>of what BizTalk Services means for Corzen and how he views it in the
broader industry context. 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d53f0e81-eebb-4327-a92f-2f2ab5fcc602" />
      </body>
      <title>Stephen Forte on what BizTalk Services means for his shop</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,d53f0e81-eebb-4327-a92f-2f2ab5fcc602.aspx</guid>
      <link>http://vasters.com/clemensv/2007/04/26/Stephen+Forte+On+What+BizTalk+Services+Means+For+His+Shop.aspx</link>
      <pubDate>Thu, 26 Apr 2007 22:09:51 GMT</pubDate>
      <description>&lt;p&gt;
Steve has a &lt;a href="http://www.stephenforte.net/owdasblog/PermaLink.aspx?guid=a8de9324-c373-4cab-8e10-4e23251a3fb4"&gt;great
analysis &lt;/a&gt;of what BizTalk Services means for Corzen and how he views it in the
broader industry context. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d53f0e81-eebb-4327-a92f-2f2ab5fcc602" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,d53f0e81-eebb-4327-a92f-2f2ab5fcc602.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>IT Strategy</category>
      <category>Technology</category>
      <category>Technology/BizTalk</category>
      <category>Technology/WCF</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=842e5373-60c1-4390-b820-00dba8b0cb4c</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,842e5373-60c1-4390-b820-00dba8b0cb4c.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,842e5373-60c1-4390-b820-00dba8b0cb4c.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=842e5373-60c1-4390-b820-00dba8b0cb4c</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <title>Internet Service Bus</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,842e5373-60c1-4390-b820-00dba8b0cb4c.aspx</guid>
      <link>http://vasters.com/clemensv/2007/04/25/Internet+Service+Bus.aspx</link>
      <pubDate>Wed, 25 Apr 2007 03:28:23 GMT</pubDate>
      <description>&lt;p&gt;
&lt;span&gt;"ESB" (for "Enterprise Service Bus") is an acronym floating around in the SOA/BPM
space for quite a while now. The notion is that you have a set of shared services
in an enterprise that act as a shared foundation for discovering, connecting and federating
services. That's a good thing and there's not much of a debate about the usefulness,
except whether &lt;a href="http://www.microsoft.com/biztalk/solutions/soa/esb.mspx"&gt;&lt;font color=#0000ff&gt;ESB&lt;/font&gt;&lt;/a&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt; is
the actual term is being used to describe this service fabric or whether there's a
concrete product with that name. Microsoft has, for instance,&amp;nbsp;directory services,
the UDDI registry, and our P2P resolution services&amp;nbsp;that contribute to the discovery
portion,&amp;nbsp;we've got BizTalk&amp;nbsp;Server as&amp;nbsp;a scalable business process, integration
and federation hub, we've got the Windows Communication Foundation for building service
oriented applications and endpoints, we've got the Windows Workflow Foundation for
building workflow-driven endpoint applications, and we have the Identity Platform
with ILM/MIIS, ADFS, and CardSpace that provides the federated identity backplane. 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Today, the division I work in (Connected Systems Division) has announced &lt;a href="http://labs.biztalk.net/"&gt;&lt;font color=#0000ff&gt;BizTalk
Services&lt;/font&gt;&lt;/a&gt;, which&amp;nbsp;John Shewchuk explains &lt;a href="http://connectedsystems.spaces.live.com/"&gt;&lt;font color=#0000ff&gt;here&lt;/font&gt;&lt;/a&gt;&amp;nbsp;and
Dennis Pilarinos drills into &lt;a href="http://www.dennispi.com/"&gt;&lt;font color=#0000ff&gt;here&lt;/font&gt;&lt;/a&gt;.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Two aspects that&amp;nbsp;make&amp;nbsp;the idea of a&amp;nbsp;"service bus" generally very
attractive&amp;nbsp;are that&amp;nbsp;the service bus&amp;nbsp;enables identity federation and
connectivity federation.&amp;nbsp;This idea gets far more interesting and more broadly
applicable when we&amp;nbsp;remove the "Enterprise" constraint from ESB it and put "Internet"
into its place, thus&amp;nbsp;elevating it to an "Internet Services Bus", or ISB.&amp;nbsp;If
we look at&amp;nbsp;the&amp;nbsp;most&amp;nbsp;popular&amp;nbsp;Internet-dependent applications outside
of the browser these days, like the many Instant Messaging apps, BitTorrent, Limewire,
VoIP, Orb/Slingbox, Skype, Halo,&amp;nbsp;Project Gotham Racing, and others,&amp;nbsp;many
of them&amp;nbsp;depend on one or two key services must be provided for each of them:
Identity Federation (or, in absence of that,&amp;nbsp;a central identity&amp;nbsp;service)
and some sort of message relay in order to connect up two or more application instances&amp;nbsp;that
each sit&amp;nbsp;behind firewalls - and at the very least&amp;nbsp;some stable, shared rendezvous
point or directory to seed P2P connections.&amp;nbsp;The question "how does&amp;nbsp;Messenger
work?" has, from an high-level architecture perspective a simple answer: The Messenger
"switchboard" acts as a message relay. 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;The problem gets really juicy when we look at the reality of what connecting
such applications means and what an ISV (or you!) were to come up with the next cool
thing on the Internet:&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;You'll soon find out that you will have to run a whole lot of server infrastructure
and the routing of all of that traffic goes through your pipes. If your cool thing
involves moving lots of large files around (let's say you'd want to build a photo
sharing app like the very unfortunately deceased &lt;a href="http://en.wikipedia.org/wiki/Microsoft_Max"&gt;&lt;font color=#0000ff&gt;Microsoft
Max&lt;/font&gt;&lt;/a&gt;) you'd&amp;nbsp;suddenly find&amp;nbsp;yourself running some significant sets
of&amp;nbsp;pipes (tubes?)&amp;nbsp;into your basement even though your users&amp;nbsp;are just
passing data from one place to the next.&amp;nbsp;That's a killer for lots of good ideas
as this represents a significant entry barrier. Interesting stuff can get popular
very, very fast these days and sometimes faster than you can say "Venture Capital".&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Messenger runs such infrastructure. And the need for such infrastructure was
indeed an (not entirely unexpected) important&amp;nbsp;takeaway from the cited Max project.
What looked just to be a very polished and cool client app to showcase all the Vista
and NETFX 3.0 goodness was just the tip of a significant iceberg of (just as cool)
server functionality that was running in a Microsoft data center to make the sharing
experience as seamless and easy as it was.&amp;nbsp;Once you want to&amp;nbsp;do cool stuff
that goes beyond the request/response browser thing, you easily end up running a data
center. And people will quickly think that your&amp;nbsp;application sucks if that data
center doesn't "just work". And that translates into several "nines" in terms of availability
in my book. And that'll cost you.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;As cool as Flickr and YouTube are, I don't think of none of them or their brethren
to be nearly as disruptive in terms of architectural paradigm shift&amp;nbsp;and long-term
technology impact as Napster, ICQ and Skype were as they appeared on the scene. YouTube
is just a place with interesting content. ICQ changed the world of collaboration.
Napster's and Skype's impact changed and is changing entire industries. The Internet
is far more and has more potential than just having some shared, mashed-up&amp;nbsp;places
where lots of people go to consume, search&amp;nbsp;and upload stuff. "Personal computing"
where I'm in control of MY stuff and share between MY places from wherever I happen
to be and NOT giving that data to someone else so that they can decorate my stuff
with ads has a future. The pendulum will swing back. I want to be able to take a family
picture with my digital camera and snap that into a digital picture frame at my dad's
house at the push of a button without some&amp;nbsp;"place" being in the middle of that.
The picture frame just has to be able to stick its head out to a place where my camera
can&amp;nbsp;talk to it so that it can accept that picture and know that it's me who is
sending it.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Another personal, and very concrete and real&amp;nbsp;point in case: I am running,
and I've written about that before,&amp;nbsp;a custom-built (software/hardware) combo
of two machines (one in Germany, one here in the US) that provide me and my family
with full Windows Media Center embedded access to live and recorded TV along with
electronic program guide data for 45+ German TV channels, Sports Pay-TV included.
The work of getting the connectivity right (dynamic DNS, port mappings, firewall holes),
dealing with the bandwidth constraints&amp;nbsp;and shielding&amp;nbsp;this against unwanted
access&amp;nbsp;were ridiculously complicated. This solution&amp;nbsp;and IP telephony and
video conferencing (over Messenger, Skype) are&amp;nbsp;shrinking the distance to home
to what's effectively just the inconvenience of the time difference of 9 hours and
that we don't see family and friends in person all that often. Otherwise we're completely
"plugged in" on what's going on at home and in Germany in general. That's an immediate
and huge improvement of the quality of living for us, is enabled by the Internet,
and has very little to do with "the Web", let alone "Web 2.0" - except that my Program
Guide app for Media Center happens to be an AJAX app today.&amp;nbsp;Using BizTalk Services
would throw out a whole lot of complexity that I had to deal with myself, especially
on the access control/identity and connectivity and discoverability fronts. Of course,
as I've done it the hard way and it's working to a degree that my wife is very happy
with it as it stands (which is the customer satisfaction metric that matters here),
I'm not making changes for technology's sake until I'm attacking the next revision
of this or I'll wait for one of the alternative and improving solutions (Orb is on
a good path) to catch up with what I have. 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;But I digress. Just as much as the services that&amp;nbsp;were just&amp;nbsp;announced
(and the ones that are lined up to follow) are a potential&amp;nbsp;enabler for new Napster/ICQ/Skype
type consumer space applications from innovative companies who don't have the capacity
or expertise to run their own data center, they are also and just as importantly the
"&lt;em&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: 'Verdana','sans-serif'"&gt;Small and Medium Enterprise&lt;/span&gt;&lt;/b&gt;&lt;/em&gt; Service
Bus". 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;If you are an ISV catering shrink-wrapped business solutions to SMEs whose network
infrastructure&amp;nbsp;may be as simple as&amp;nbsp;a DSL line (with dynamic IP) that goes
into a (wireless) hub and is as locked down as it possibly can be by the local networking
company that services them, we can do as much as we want as an industry in trying
to make inter-company B2B work and expand it to SMEs;&amp;nbsp;your customers just aren't
playing in that game if they can't&amp;nbsp;get over these basic connectivity hurdles. 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Your app, that lives behind the firewall shield and NAT and a dynamic IP,&amp;nbsp;doesn't
have a stable, public place where it can publish its endpoints and you have no way
to federate identity (and access control)&amp;nbsp;unless you are doing some pretty invasive
surgery on their network setup&amp;nbsp;or you&amp;nbsp;end up building and running run a
bunch of infrastructure on-site or for them. And that's the same problem as the mentioned
consumer apps have.&amp;nbsp;Even more so, if you look at the list of "coming soon" services,
you'll find that problems like relaying events or coordinating work with workflows
are very suitable for&amp;nbsp;many common use-cases in SME business applications once
you imagine expanding their scope to inter-company collaboration.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;So where's "Megacorp Enterprises" in that play? First of all, Megacorp isn't
an island. Every Megacorp depends on lots of SME suppliers and retailers (or their
equivalents in the respective lingo of the verticals). Plugging all of them directly
into&amp;nbsp;Megacorp's "ESB" often isn't feasible for lots of reasons and increasingly
less so if the SME had a second or third (imagine that!) customer and/or supplier.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Second, Megacorp isn't a uniform big&amp;nbsp;entity.&amp;nbsp;The count of "enterprise
applications" running inside of Megacorp is measured in thousands rather than dozens.
We're often inclined to think of SAP or Siebel when we think of enterprise applications,&amp;nbsp;but
the vast majority are much simpler and more scoped than that. It's not entirely ridiculous
to think that&amp;nbsp;some of those applications runs (gasp!) under someone's desk or
in a cabinet in an extra room of a department.&amp;nbsp;And it's also not entirely ridiculous
to think that these applications are so vertical and special that their integration
into the "ESB" gets continuously overridden by someone else's higher priorities and
yet, the respective business department needs a very practical way to connect with
partners &lt;em&gt;&lt;span style="FONT-FAMILY: 'Verdana','sans-serif'"&gt;now&lt;/span&gt;&lt;/em&gt; and
be "connectable" even though it sits deeply inside the network thicket of Megacorp.
While it is likely on every CIO's&amp;nbsp;goal sheet to contain that sort of IT anarchy,
it's a reality that needs answers in order to keep the business bring in the money.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Third, Megacorp needs to work with Gigacorp. To make it interesting, let's assume
that Megacorp and Gigacorp don't like each other much and trust each other even less.
They even compete. Yet, they've got to work on a standard and hence they need to collaborate.
It turns out that this scenario is almost entirely the same as the "Panic! Our departments
take IT in their own hands!" scenario described above. At most, Megacorp wants to
give Gigacorp a rendezvous and identity federation point on neutral ground. So instead
of letting Gigacorp on their ESB, they both hook their apps and their identity infrastructures
into the ISB and let the ISB be the mediator in that play.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Bottom line: There are very many solution scenarios, of which I mentioned just
a few,&amp;nbsp;where "I" is&amp;nbsp;a much&amp;nbsp;more suitable&amp;nbsp;scope than "E". Sometimes&amp;nbsp;the
appropriate scope is just "I", sometimes the appropriate scope is just "E". They key
to achieve the agility that SOA strategies commonly promise is the ability to do the
"E to I" scale-up whenever you need it in order to enable broader communication. If
you need to elevate one or a set services from your ESB to Internet scope, you have
the option to go and do so as appropriate and integrated with your identity infrastructure.&amp;nbsp;And
since this all strictly WS-* standards based, your "E" might actually be "whatever
you happen to run today".&amp;nbsp;BizTalk Services is&amp;nbsp;the "I".&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;Or, in other words,&amp;nbsp;&lt;a href="http://labs.biztalk.net/"&gt;&lt;font color=#0000ff&gt;this
is a pretty big deal.&lt;/font&gt;&lt;/a&gt; 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=842e5373-60c1-4390-b820-00dba8b0cb4c" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,842e5373-60c1-4390-b820-00dba8b0cb4c.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>IT Strategy</category>
      <category>Microsoft</category>
      <category>MSDN</category>
      <category>Technology/BizTalk</category>
      <category>Technology/WCF</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=700e8619-de82-4ecb-8c3f-ad60b001cf47</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,700e8619-de82-4ecb-8c3f-ad60b001cf47.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,700e8619-de82-4ecb-8c3f-ad60b001cf47.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=700e8619-de82-4ecb-8c3f-ad60b001cf47</wfw:commentRss>
      <title>Services and the Business/IT Gap</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,700e8619-de82-4ecb-8c3f-ad60b001cf47.aspx</guid>
      <link>http://vasters.com/clemensv/2006/05/30/Services+And+The+BusinessIT+Gap.aspx</link>
      <pubDate>Tue, 30 May 2006 15:30:59 GMT</pubDate>
      <description>&lt;div class=Section1&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;Recently, a gentleman from Switzerland wrote me an email after attending
the “WinFX Tour” presentations in Zurich. He is a business consultant advising corporations
on the IT strategy and an IT industry veteran with his first programming work dating
as long back as 1962. He was quite interested in the Workflow part of my presentation,
but wrote me that he thinks that those abstraction efforts go the wrong way. He sees
the fundamental gap between business and IT widening and sees very little hope for
the two sides to ever find a way to communicate effectively with each other. In his
view, IT isn’t truly interested in the reality of business. He wrote me a very long
email with several statements and questions, which I won’t quote – the (very long)
reply below should give you enough context:&lt;/span&gt;&lt;span lang=EN-US&gt;&lt;?xml:namespace prefix = o /&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;Your main concern is, in my words, about the
disconnect between the reality of the business vs. the snapshot of a perceived business
reality that is translated into a software system. I say “perceived” because the capturing
of the actual business reality is done by analysts who are on the fence between being
business experts and IT experts and even though they would ideally be geniuses in
both worlds to do that translation, they often are coming down on one side of that
fence in terms of their core competencies. &amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;The only way to close that gap is to pull people
off that fence onto the business side and enable them to capture the reality of the
business and the way the business processes flow with tools that fit their needs and
don’t demand that they are programmers or even have the sense of abstraction that
a software designer or process analyst possesses. Our industry is only starting to
understand what is required to achieve this and we are certainly thinking hard about
these problems.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;You state that the Business/IT gap cannot be
bridged. I do not fully agree with that assessment. I think what you are observing
is a particular effect of software architecture and implementation as it exists today.
You are truly an “industry veteran” you can certainly see much clearer how software
has evolved since you got into the trade in 1962 than I can as a relative youngling.
However, my (humble) observation is that the fundamental concepts of business software
design haven’t changes all that much since then. A business application is a scoped
set of siloed functionality built for a set of predefined purposes and whether the
user interacts with the system through batch jobs, green screens, web sites or whether
the system is made up of 5000 identical fat client applications with identical logic
that talk to a central database is merely an implementation detail. The tradition
of (interactive) business software is very much that we’ve got a system with some
sort of menu screen or other form of selecting the task you want to perform with the
system and any number of forms/screens/dialogs with which you can interact with the
system. The reason for your observation of IT conveniently neglecting at least 20%
of what they are told to do is not only caused by them not understanding the business,
but also caused by them being not in control of the monsters they create because the
scope grows too big, everything is tightly coupled to everything else, and a lot of
functionalities are crammed together in ”multi-purpose” user interfaces that often
make changes or adjustments mutually exclusive and hence “impossible”.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;The actual business process is often external
to the software or if the software has workflow guidance, the workflows are not taking
all the “offline” activities into account and the process becomes lossy. The way that
most applications are built today is that they present the user with a grab-bag of
tools and procedures and leaves it up to them to navigate through it. Even worse,
business processes are often changed to fit the constraints of software – and not
the other way around. Testimony for this is that the organizational structure of many
companies is hardly recognizable once the SAP/PeopleSoft/Oracle/etc. ERP consultants
have left the building.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;So what’s changing with the SOA/BPM “hype” as
you call it? Or I shall better say: What’s the opportunity? &amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;First, we’re working hard to get to a point where
we can build interoperable, autonomous pieces of software with well-defined interfaces
where we don’t have to spend 80% of our time and money trying to make those pieces
communicate with each other. Before the industry consensus around XML, SOAP and the
WS-* specifications this most fundamental requirement for breaking up the solution
silos simple didn’t exist (despite previous efforts like DCE or CORBA). I am not saying
that we have completely arrived at that point, but we’ve got a better foundation than
ever to build composable, loosely coupled, distributed systems that can interact irrespective
of their implementation specifics.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;Second, we are starting to see growing insight
on the IT side for the need of a common understanding of the idea of “services”. Any
employee, department, division or vendor assumes various roles within an organization
and renders a certain portfolio of services towards the organization. The notion of
service-oriented architecture speaks about writing software that fits into the organization
instead of fitting the organization to the software. Just like an employee assumes
roles, software assumes roles as well. From an architecture perspective, people and
software are peers collaborating on the same business task. The former are just a
lot more flexible than the latter.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;Business processes (or bureaucracy), whether
formalized or ad-hoc, are driven by the flow of information. If the information flow
is not central to the execution of the process you have friction and efficiency suffers.
With a paper-bound “offline” process where all information flows in a (paper-) file
folder and on forms carried by courier from department to department there’s arguably
a better and more complete information flow than in an environment where information
is scattered around dozens of different computer systems where the flow of information
and the flow of tasks are disconnected and only knitted together by people shuffling
mice around on their desks.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;The opportunity is right at that point. With
the technology we have available and a common notion of “services”, the line between
the implementation of deterministic work (done by programs) and non-deterministic
work (done by humans) begins to blur. It is fairly easy today to write chat-bots,
mail-bots, or speech-enabled services that allow rich computer/human interaction within
their respective scope. It is likewise fairly easy to expose application to application
services that allow exchanging rich data across system and platform boundaries using
Web Services. The concrete form of how a service interacts with a peer depends on
who the peer is. If you have an address book lookup service, it may have all of these
capabilities at once. With that, services can be integrated into real-life ad-hoc
scenarios singly or in combination because they are built to satisfy specific roles
and their capabilities are exposed for (re)use in arbitrary contexts. &amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;When you have a service that’s specialized on
creating complex sales offers and you are a salesman on the road an sit in a taxi,
it’s absolutely fathomable to build a solution that allows you to call in, identify
yourself towards a voice service and ask for an baseline offer for 500 units of A
and 300 units of B for a specific customer and have the result, with all applicable
rebates and possible delivery time frames, including shipping cost and considering
the schedule of the container freighter ship from China, pushed onto your hotel fax
or by email or SMS/MMS. However, the question of how realistic it is to build that
service purely depends on how easy it is to make all the necessary backend systems
talk to each other and wire up all the roles into a process that can jointly accomplish
the task. And it also depends on how well any necessary human intervention into that
process can be integrated into the respective flow. Assuming that the resulting offer
would cross a certain threshold in terms of the total order amount, the offer might
require approval by a manager – the manager renders a “decision service” towards the
process and might so by responding to an email that is sent to him/her by a program
and will be evaluated by a program. &amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;Ideally, you could teach a service (through mail,
speech or chat) the workflow ad-hoc just as you would tell an administrative assistant
a sequence of activities. “Get A and B, do C, let Mike take a look at it and send
it to me”. The information can be parsed, mapped to activities, the activities can
be wired up to a one-off workflow and the workflow can be launched. The crux is that
you need to have those individual capabilities and activities catalogued and available
in a fashion that allows composition. And the above example of the approval manager
goes to show that people’s roles and capabilities must be part of that same catalogue.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;We (Microsoft) are already shipping and will
ship even more building blocks not only for creating such services and workflows,
but we also have an increasingly complete federated identity and access control infrastructure
that allows to realize all that decentralized interaction in a secure fashion. From
a purely technical perspective, the above scenario is not utopia. We have every single
component in place to let customers build this, voice recognition included. However,
mind that I am not saying “very easy”.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;“BPM” tools such as the Windows Workflow Foundation
or BizTalk Orchestration are all about putting the process into the center. Services
are all about creating easy-to-integrate, loosely coupled, business-aligned pieces
of functionality that can be used and reused in as many contexts as a role in a business
can be used in different contexts. A workflow may just be one step that you just have
in your head as you are interacting with the address lookup service or it may be a
more formalized workflow with several steps and intertwined people-based and program-based
activities. The realization here is that while individual roles in an organization
are relatively sticky, the way that the organization acts across those roles and tunes
the rules for the roles is very dynamic. BPM tools are precisely about shaping and
reshaping the flow and rules quickly and deploying those instantly into the business
environment.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;The design of the Windows Workflow Foundation
also recognizes that business processes, especially those that run for days and weeks
rather than seconds or minutes, are never set in stone. If you’ve got a (very) long
running master workflow that were, for instance, tracking an insurance policy and
applies rebates and handles claims as time progresses and suddenly the client comes
around and sues the insurance company, that policy certainly no longer belongs into
the same bucket as the other 100000s of policies that are being tracked. So for such
unforeseeable circumstances, the foundation makes it possible to jump right in, assess
the status and redirect or reshape the respective flow on a case-by-case basis and
if the new action that you add into the flow in order to terminate it is merely that
you hand off the entire case with all of its status to your legal department’s “dropoff
service”.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;You write about SO/A and BPM as an “effort to
extend the borders of IT”. From my perspective it’s rather the attempt by IT to humbly
fit itself into the ever changing dynamic nature of business. On an industry level
we have started to realize that we need to get away from the thinking that applications
are silos and that nobody should factually care about whether he/she interacts with
a “CRM” or “ERP” system or needs to navigate across a dozen of intranet websites to
get a job done. The whole notion of “we build a loan application handling program”
is indeed misguided. That’s the disconnect.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;But how alien is the notion of building a library
of services that are not wired up into a thing that you can install and instantly
run as a program? We hire people into organizations who have a broad education if
which we only tap a fraction at any given point in time, but we can trust that we
can instantly tap some other capability as the process changes. Which CEO/CFO/CIO
will commit to a project that “educates” a software system to have a broad spectrum
of capabilities that may or may not be used in the circumstances of “now” but which
may become a pressing necessity as you need to quickly adapt to a change in the business?
How strange of an idea is it that you might produce a software package that consists
of hundreds of roles and thousands of activities but none of them are connected in
any way, because that’s the job of the space that’s intentionally left blank and undefined
to host the customized business process? How does the buyer justify the expense? What
can the vendor charge? Would you continually service and update a “dormant” software-based
capability to the latest policies, laws and regulations so that it can be used whenever
the need arises?&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN-LEFT: 35.4pt"&gt;
&lt;span lang=EN-US&gt;&lt;font color=#000080&gt;All that comes back to a completely different
communication breakdown: How does IT explain that sort of perspective to the business
stakeholders? The great challenge is not in the bits, it’s in the heads.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=700e8619-de82-4ecb-8c3f-ad60b001cf47" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,700e8619-de82-4ecb-8c3f-ad60b001cf47.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p class="Section1">
          <b>Inside the big house....</b>
        </p>
        <p class="Section1">
Back in December of last year and about two weeks before I publicly announced
that I will be working from Microsoft, <a href="http://friends.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx">I
started</a> a nine-part series on REST/POX* programming with <strike>Indigo</strike> WCF. (<span lang="DE"><a title="http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx" href="http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx"><span lang="EN-US"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx">1</span></span></span></span></a></span>, <span lang="DE"><a title="http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx" href="http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx"><span lang="EN-US"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx">2</span></span></span></span></a></span>, <span lang="DE"><a title="http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx" href="http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx"><span lang="EN-US"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx">3</span></span></span></span></a></span>, <span lang="DE"><a title="http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx" href="http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx"><span lang="EN-US"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx"><span title="http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx">4</span></span></span></span></a></span>, <a title="http://staff.newtelligence.net/clemensv/PermaLink,guid,3712ee6b-cd80-4db3-a96c-c740491f588e.aspx" href="http://staff.newtelligence.net/clemensv/PermaLink,guid,3712ee6b-cd80-4db3-a96c-c740491f588e.aspx">5</a>, <a title="http://staff.newtelligence.net/clemensv/PermaLink,guid,51327201-07c7-4a30-b79c-53842cda1e77.aspx" href="http://staff.newtelligence.net/clemensv/PermaLink,guid,51327201-07c7-4a30-b79c-53842cda1e77.aspx">6</a>, <a title="http://staff.newtelligence.net/clemensv/PermaLink,guid,e82c8423-f106-4105-81e4-14410a83315a.aspx" href="http://staff.newtelligence.net/clemensv/PermaLink,guid,e82c8423-f106-4105-81e4-14410a83315a.aspx">7</a>, <a href="http://staff.newtelligence.net/clemensv/PermaLink,guid,7465c74e-6001-4d08-93ae-ad7110dee188.aspx">8</a>, <a href="http://friends.newtelligence.net/clemensv/PermaLink,guid,8fc367b2-a4be-4588-8264-5455c268b94a.aspx">9</a>).
Since then, the WCF object model has seen quite a few feature and usability improvements
across the board and those are significant enough to justify that I rewrite the entire
series to get it up to the February CTP level and I will keep updating it through
Vista/WinFX Beta2 and as we are marching towards our RTM. We've got a few changes/extensions
in our production pipeline to make the REST/POX story for WCF v1 stronger and
I will track those changes with yet another re-release of this series. 
</p>
        <p class="Section1">
Except in one or two occasions, I haven't re-posted a reworked story on my blog. This
here is quite a bit different, because of it sheer size and the things I learned in
the process of writing it and developing the code along the way. So even though it
is relatively new, it's already due for an end-to-end overhaul to represent my current
thinking. It's also different, because I am starting to cross-post content to <a href="http://blogs.msdn.com/clemensv">http://blogs.msdn.com/clemensv</a> with
this post; however <a href="http://friends.newtelligence.net/clemensv">http://friends.newtelligence.net/clemensv</a> remains my
primary blog since that runs my engine ;-)
</p>
        <p class="Section1">
          <strong>Listening</strong>
        </p>
        <p class="Section1">
The "current thinking" is of course very much influenced by now working for the team
that builds WCF instead of being a customer looking at things from the outside. That
changes the perspective quite a bit. One great insight I gained is how non-dogmatic
and customer-oriented our team is. When I started the concrete REST/POX work with
WCF back in last September (on the customer side still working with newtelligence),
the extensions to the HTTP transport that enabled this work were just showing
up in the public builds and they were sometimes referred to as the "<a href="http://pluralsight.com/blogs/tewald">Tim</a>/<a href="http://www.pluralsight.com/blogs/aaron/">Aaaron</a> feature".
Tim Ewald and Aaron Skonnard had beat the drums for having simple XML (non-SOAP) support
in WCF so loudly that the team investigated the options and figured that some minimal
changes to the HTTP transport would enable most of these scenarios**. Based on
that feature, I wrote the set of dispatcher extensions that I've been presenting in the
V1 of this series and <a href="http://newtellivision.tv">newtellivision</a> as
the applied example did not only turn out to be a big hit as a demo,
it also was one of many motivations to give the REST/POX scenario even deeper
consideration within the team. 
</p>
        <p class="Section1">
REST/POX is a scenario we think about as a first-class scenario alongside SOAP-based
messaging - we are working with the ASP.NET Atlas team to integrate WCF with their
AJAX story and we continue to tweak the core WCF product to enable those scenarios
in a more straightforward fashion. Proof for that is that my talk (<a href="http://216.55.183.13/mix06/BTB021_Vasters.ppt">PPT
here</a>) at the <a href="http://www.mix06.com/">MIX06 conference</a> in Las
Vegas two weeks ago was entirely dedicated to the non-SOAP scenarios.
</p>
        <p class="Section1">
What does that say about SOAP? Nothing. There are two parallel worlds of application-level
network communication that live in peaceful co-existence:
</p>
        <div class="Section1">
          <ul>
            <li>
Simple point-to-point, request/response scenarios with limited security requirements
and no need for "enterprise features" along the lines of reliable messaging and transaction
integration. 
</li>
            <li>
Rich messaging scenarios with support for message routing, reliable delivery, discoverable
metadata, out-of-band data, transactions, one-way and duplex, etcetc.</li>
          </ul>
        </div>
        <p>
          <strong>The Faceless Web</strong>
        </p>
        <p>
The first scenario is the web as we know it. Almost. HTTP is an incredibly rich
application protocol once you dig into RFC2616 and look at the methods in detail
and consider response codes beyond 200 and 404. HTTP is strong because it
is well-defined, widely supported and designed to scale, HTTP is weak because it is
effectively constrained to request/response, there is no story for server-to-client
notifications and it abstracts away the inherent reliability of the transmission-control
protocol (TCP). These pros and cons lists are not exhaustive.
</p>
        <p>
What REST/POX does is to elevate the web model above the "you give me <em>text/html</em> or <em>*/*</em> and
I give you <em>application/x-www-form-urlencoded</em>" interaction model. Whether
the server punts up markup in the form of text/html or text/xml or some other angle-bracket
dialect or some raw binary isn't too interesting. What's changing the way applications
are built and what is really creating the foundation for, say, AJAX is that the path
back to the server is increasingly XML'ised. PUT and POST with a content-type
of text/xml is significantly different from <em>application/x-www-form-urlencoded</em>.
What we are observing is the emancipation of HTTP from HTML to a degree that
the "HT" in HTTP is becoming a misnomer. Something like IXTP ("Interlinked XML Transport
Protocol" - I just made that up) would be a better fit by now.
</p>
        <p>
The astonishing bit in this is that there has been been no fundamental technology
change that has been driving this. The only thing I can identify is that browsers
other than IE are now supporting XMLHTTP and therefore created the critical mass
for broad adoption. REST/POX rips the face off the web and enables a separation
of data and presentation in a way that mashups become easily possible and we're driving
towards a point where the browser cache becomes more of an application repository
than merely a place that holds cacheable collateral. When developing the
newtellivision application I have spent quite a bit of time on tuning the caching
behavior in a way that HTML and script are pulled from the server only when necessary
and as static resources and all actual interaction with the backend services happens
through XMLHTTP and in REST/POX style. newtellivision is not really a hypertext website,
it's more like a smart client application that is delivered through the web technology
stack.
</p>
        <p>
          <strong>Distributed Enterprise Computing</strong>
        </p>
        <p>
All that said, the significant investments in SOAP and WS-* that were made my Microsoft
and industry partners such as Sun, IBM, Tibco and BEA have their primary justification
in the parallel universe of highly interoperable, feature-rich intra and inter-application
communication as well as in enterprise messaging. Even though there was a two-way
split right through through the industry in the 1990s with one side adopting the Distributed
Computing Environment (DCE) and the other side driving the Common Object Request Broker
Architecture (CORBA), both of these camps made great advances towards rich, interoperable
(within their boundaries) enterprise communication infrastructures. All of that got
effectively killed by the web gold-rush starting in 1994/1995 as the focus (and investment) in
the industry turned to HTML/HTTP and to building infrastructures that supported the
web in the first place and everything else as a secondary consideration. The direct
consequence of the resulting (even if big) technology islands hat sit underneath the
web and the neglect of inter-application communication needs was that inter-application
communication has slowly grown to become one of the greatest industry problems and
cost factors. Contributing to that is that the average yearly number of corporate
mergers and acquisitions has tripled compared to 10-15 years ago (even though the
trend has slowed in recent years) and the information technology dependency of
today's corporations has grown to become one of the deciding if not the deciding competitive
factor for an ever increasing number of industries.
</p>
        <p>
What we (the industry as a whole) are doing now and for the last few years is that
we're working towards getting to a point where we're both writing the next chapter
of the story of the web and we're fixing the distributed computing story at the same
time by bringing them both onto a commonly agreed platform. The underpinning of that
is XML; REST/POX is the simplest implementation. SOAP and the WS-* standards
elevate that model up to the distributed enterprise computing realm. 
</p>
        <p>
If you compare the core properties of <a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/">SOAP</a>+<a href="http://www.w3.org/TR/ws-addr-core/">WS-Adressing</a> and
the <a href="http://www.ietf.org/rfc/rfc2460.txt">Internet Protocol</a> (IP) in an
interpretative fashion side-by-side and then also compare the <a href="http://www.ietf.org/rfc/rfc793.txt">Transmission
Control Protocol</a> (TCP) to <a href="http://msdn.microsoft.com/ws/2005/02/ws-reliablemessaging/">WS-ReliableMessaging</a> it
may become quite clear to you what a fundamental abstraction above the networking
stacks and concrete technology coupling the WS-* specification family has become.
Every specification in the <a href="http://msdn.microsoft.com/webservices/webservices/understanding/specs/default.aspx">long
list</a> of WS-* specs is about converging and unifying formerly proprietary approaches
to messaging, security, transactions, metadata, management, business process management
and other aspects of distributed computing into this common platform.
</p>
        <p>
          <strong>Convergence</strong>
        </p>
        <p>
The beauty of that model is that it is an implementation superset of the
web. SOAP is the out-of-band metadata container for these abstractions. The
key feature of SOAP is SOAP:Header, which provides a standardized facility to
relay the required metadata alongside payloads. If you are willing to constrain out-of-band
metadata to one transport or application protocol, you don't need SOAP. 
</p>
        <p>
There is really very little difference between SOAP and REST/POX in terms of the information
model. SOAP carries headers and HTTP carries headers. In HTTP they are bolted to the
protocol layer and in SOAP they are tunneled through whatever carries the envelope. [In
that sense, SOAP is calculated abuse of HTTP as a transport protocol for the purpose
of abstraction.] You can map WS-Addressing headers from and to HTTP headers. 
</p>
        <p>
The SOAP/WS-* model is richer, more flexible and more complex. The SOAP/WS-* set of
specifications is about infrastructure protocols. HTTP is an application protocol
and therefore it is naturally more constrained - but has inherently defined qualities
and features that require an explicit protocol implementation in the SOAP/WS-* world;
one example is the inherent CRUD (create, read, update, delete) support in HTTP that
is matched by the explicitly composed-on-top WS-Transfer protocol in SOAP/WS-*
</p>
        <p>
The common platform is XML. You can scale down from SOAP/WS-* to REST/POX by putting
the naked payload on the wire and rely on HTTP for your metadata, error and status
information if that suits your needs. You can scale up from REST/POX to SOAP/WS-*
by encapsulating payloads and leverage the WS-* infrastructure for all the
flexibility and features it brings to the table. [It is fairly straightforward to
go from HTTP to SOAP/WS-*, and it is harder to go the other way. That's why I say
"superset".]
</p>
        <p>
Doing the right thing for a given scenario is precisely what are enabling in
WCF. There is a place for REST/POX for building the surface of the mashed and
faceless web and there is a place for SOAP for building the backbone of it - and some
may choose to mix and match these worlds. There are many scenarios and architectural
models that suit them. What we want is 
</p>
        <p align="center">
          <strong>One Way To Program</strong>. 
</p>
        <p>
          <font size="1">* REST=REpresentational State Transfer; POX="Plain-Old XML" or "simple
XML"</font>
        </p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c" />
      </body>
      <title>REST/POX with WCF: Version 2, Part 1: Foreword</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c.aspx</guid>
      <link>http://vasters.com/clemensv/2006/04/01/RESTPOX+With+WCF+Version+2+Part+1+Foreword.aspx</link>
      <pubDate>Sat, 01 Apr 2006 12:25:42 GMT</pubDate>
      <description>&lt;p class=Section1&gt;
&lt;b&gt;Inside the big house....&lt;/b&gt;
&lt;/p&gt;
&lt;p class=Section1&gt;
Back in&amp;nbsp;December of last year and about two weeks before I publicly announced
that I will be working from Microsoft, &lt;a href="http://friends.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx"&gt;I
started&lt;/a&gt; a&amp;nbsp;nine-part series on REST/POX* programming with&amp;nbsp;&lt;strike&gt;Indigo&lt;/strike&gt; WCF.&amp;nbsp;(&lt;span lang=DE&gt;&lt;a title=http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx href="http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx"&gt;&lt;span lang=EN-US&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,2d61b97b-3a6e-46bd-89db-b1b20499ba18.aspx&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span lang=DE&gt;&lt;a title=http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx href="http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx"&gt;&lt;span lang=EN-US&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,4e2a7d26-342c-4402-8000-a0d15860c5fc.aspx&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span lang=DE&gt;&lt;a title=http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx href="http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx"&gt;&lt;span lang=EN-US&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,3f40268c-dee2-44eb-829a-f621a4d40fbc.aspx&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;, &lt;span lang=DE&gt;&lt;a title=http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx href="http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx"&gt;&lt;span lang=EN-US&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx&gt;&lt;span title=http://staff.newtelligence.net/clemensv/PermaLink,guid,c45eb508-2269-4d0e-a730-dbd9c7d5f882.aspx&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;, &lt;a title=http://staff.newtelligence.net/clemensv/PermaLink,guid,3712ee6b-cd80-4db3-a96c-c740491f588e.aspx href="http://staff.newtelligence.net/clemensv/PermaLink,guid,3712ee6b-cd80-4db3-a96c-c740491f588e.aspx"&gt;5&lt;/a&gt;, &lt;a title=http://staff.newtelligence.net/clemensv/PermaLink,guid,51327201-07c7-4a30-b79c-53842cda1e77.aspx href="http://staff.newtelligence.net/clemensv/PermaLink,guid,51327201-07c7-4a30-b79c-53842cda1e77.aspx"&gt;6&lt;/a&gt;, &lt;a title=http://staff.newtelligence.net/clemensv/PermaLink,guid,e82c8423-f106-4105-81e4-14410a83315a.aspx href="http://staff.newtelligence.net/clemensv/PermaLink,guid,e82c8423-f106-4105-81e4-14410a83315a.aspx"&gt;7&lt;/a&gt;, &lt;a href="http://staff.newtelligence.net/clemensv/PermaLink,guid,7465c74e-6001-4d08-93ae-ad7110dee188.aspx"&gt;8&lt;/a&gt;, &lt;a href="http://friends.newtelligence.net/clemensv/PermaLink,guid,8fc367b2-a4be-4588-8264-5455c268b94a.aspx"&gt;9&lt;/a&gt;).
Since then, the WCF object model has seen quite a few feature and usability improvements
across the board and those are significant enough to justify that I rewrite the entire
series to get it up to the February CTP level and I will keep updating it through
Vista/WinFX Beta2 and as we are marching towards our RTM. We've got a few changes/extensions
in&amp;nbsp;our production pipeline to make the REST/POX story for WCF v1 stronger and
I will track those changes with yet another re-release of this series. 
&lt;/p&gt;
&lt;p class=Section1&gt;
Except in one or two occasions, I haven't re-posted a reworked story on my blog. This
here is quite a bit different, because of it sheer size and the things I learned in
the process of writing it and developing the code along the way. So even though it
is relatively new, it's already due for an end-to-end overhaul to represent my current
thinking. It's also different, because I am starting to cross-post content to &lt;a href="http://blogs.msdn.com/clemensv"&gt;http://blogs.msdn.com/clemensv&lt;/a&gt;&amp;nbsp;with
this post;&amp;nbsp;however &lt;a href="http://friends.newtelligence.net/clemensv"&gt;http://friends.newtelligence.net/clemensv&lt;/a&gt; remains&amp;nbsp;my
primary blog since that runs my engine ;-)
&lt;/p&gt;
&lt;p class=Section1&gt;
&lt;strong&gt;Listening&lt;/strong&gt;
&lt;/p&gt;
&lt;p class=Section1&gt;
The "current thinking" is of course very much influenced by now working for the team
that builds WCF instead of being a customer looking at things from the outside. That
changes the perspective quite a bit. One&amp;nbsp;great insight I gained is how non-dogmatic
and customer-oriented our team is. When I started the concrete REST/POX work with
WCF back in last September (on the customer side still working with newtelligence),
the extensions to the HTTP transport that&amp;nbsp;enabled this work were just showing
up in the public builds and they were&amp;nbsp;sometimes referred to as the&amp;nbsp;"&lt;a href="http://pluralsight.com/blogs/tewald"&gt;Tim&lt;/a&gt;/&lt;a href="http://www.pluralsight.com/blogs/aaron/"&gt;Aaaron&lt;/a&gt; feature".
Tim Ewald and Aaron Skonnard had beat the drums for having simple XML (non-SOAP) support
in WCF so loudly that the team investigated the options and figured that some minimal
changes to the HTTP transport would enable most of these scenarios**.&amp;nbsp;Based on
that feature, I wrote the set of dispatcher extensions that I've been presenting in&amp;nbsp;the
V1 of this&amp;nbsp;series and &lt;a href="http://newtellivision.tv"&gt;newtellivision&lt;/a&gt; as
the applied example did not only&amp;nbsp;turn out to be a big hit&amp;nbsp;as a&amp;nbsp;demo,
it also was&amp;nbsp;one of many&amp;nbsp;motivations to give the REST/POX scenario even deeper
consideration within the team. 
&lt;/p&gt;
&lt;p class=Section1&gt;
REST/POX is a scenario we&amp;nbsp;think about as a first-class scenario alongside SOAP-based
messaging - we are working with the ASP.NET Atlas team to integrate WCF with their
AJAX story and&amp;nbsp;we continue to tweak the core WCF product to enable those scenarios
in a more straightforward fashion. Proof for that is that my talk (&lt;a href="http://216.55.183.13/mix06/BTB021_Vasters.ppt"&gt;PPT
here&lt;/a&gt;)&amp;nbsp;at the &lt;a href="http://www.mix06.com/"&gt;MIX06 conference&lt;/a&gt; in Las
Vegas two weeks ago was entirely dedicated&amp;nbsp;to the non-SOAP&amp;nbsp;scenarios.
&lt;/p&gt;
&lt;p class=Section1&gt;
What does that say about SOAP? Nothing. There are two parallel worlds of application-level
network communication that live in peaceful co-existence:
&lt;/p&gt;
&lt;div class=Section1&gt;
&lt;ul&gt;
&lt;li&gt;
Simple point-to-point, request/response&amp;nbsp;scenarios with limited security requirements
and no need for "enterprise features" along the lines of reliable messaging and transaction
integration. 
&lt;/li&gt;
&lt;li&gt;
Rich messaging scenarios with support for&amp;nbsp;message routing, reliable delivery,&amp;nbsp;discoverable
metadata, out-of-band data,&amp;nbsp;transactions, one-way and duplex, etcetc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;The Faceless Web&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
The first scenario is the web as we know it. Almost.&amp;nbsp;HTTP is an incredibly rich
application protocol once you&amp;nbsp;dig into RFC2616 and look at the methods in detail
and consider response codes beyond 200 and 404.&amp;nbsp;HTTP is&amp;nbsp;strong because it
is well-defined, widely supported and designed to scale, HTTP is weak because it is
effectively constrained to request/response, there is no story for server-to-client
notifications and it abstracts away the inherent reliability of the transmission-control
protocol (TCP).&amp;nbsp;These pros and cons&amp;nbsp;lists are not exhaustive.
&lt;/p&gt;
&lt;p&gt;
What REST/POX does is to elevate the web model above the "you give me &lt;em&gt;text/html&lt;/em&gt; or &lt;em&gt;*/*&lt;/em&gt; and
I give you &lt;em&gt;application/x-www-form-urlencoded&lt;/em&gt;" interaction model. Whether
the server punts up markup in the form of text/html or text/xml or some other angle-bracket
dialect or some raw binary isn't too interesting. What's changing the way applications
are built and what is really creating the foundation for, say, AJAX is that the path
back to the server is increasingly XML'ised.&amp;nbsp;PUT and POST&amp;nbsp;with a content-type
of text/xml is significantly different from &lt;em&gt;application/x-www-form-urlencoded&lt;/em&gt;.
What we are&amp;nbsp;observing is the emancipation of HTTP from HTML to a degree that
the "HT" in HTTP is becoming a misnomer. Something like IXTP ("Interlinked XML Transport
Protocol" - I just made that up) would be a better fit by now.
&lt;/p&gt;
&lt;p&gt;
The astonishing bit in this is that there has been&amp;nbsp;been no&amp;nbsp;fundamental technology
change that has been driving this. The only thing I can identify is that browsers
other than IE are now supporting XMLHTTP and&amp;nbsp;therefore created the critical mass
for&amp;nbsp;broad adoption. REST/POX rips the face off the web and enables a separation
of data and presentation in a way that mashups become easily possible and we're driving
towards a point where the browser cache becomes more of an application repository
than merely a place that holds cacheable collateral.&amp;nbsp;When developing&amp;nbsp;the
newtellivision application I have spent quite a bit of time on tuning the caching
behavior in a way that HTML and script are pulled from the server only when necessary
and as static resources and all actual interaction with the backend services happens
through XMLHTTP and in REST/POX style. newtellivision is not really a hypertext website,
it's more like a smart client application that is delivered through the web technology
stack.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Distributed Enterprise Computing&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
All that said, the significant investments in SOAP and WS-* that were made my Microsoft
and industry partners such as Sun, IBM, Tibco and BEA&amp;nbsp;have their primary justification
in the parallel universe of highly interoperable, feature-rich&amp;nbsp;intra and inter-application
communication as well as in enterprise messaging. Even though there was a two-way
split right through through the industry in the 1990s with one side adopting the Distributed
Computing Environment (DCE) and the other side driving the Common Object Request Broker
Architecture (CORBA), both of these camps made great advances towards rich, interoperable
(within their boundaries) enterprise communication infrastructures. All of that got
effectively killed by the web gold-rush starting in 1994/1995 as the focus (and investment)&amp;nbsp;in
the industry turned to HTML/HTTP and to building infrastructures that supported the
web in the first place and everything else as a secondary consideration. The direct
consequence of the resulting (even if big) technology islands hat sit underneath the
web and the neglect of inter-application communication needs was that inter-application
communication has slowly grown to become&amp;nbsp;one of the greatest industry problems&amp;nbsp;and
cost factors. Contributing to that is that the average yearly number of corporate
mergers and acquisitions has tripled compared to 10-15 years ago (even though the
trend has slowed in recent years) and the information technology&amp;nbsp;dependency of
today's corporations has grown to become one of the deciding if not the deciding competitive
factor for&amp;nbsp;an ever increasing number of industries.
&lt;/p&gt;
&lt;p&gt;
What we (the industry as a whole) are doing now and for the last few years is that
we're working towards getting to a point where we're both writing the next chapter
of the story of the web and we're fixing the distributed computing story at the same
time by bringing them both onto a commonly agreed platform. The underpinning of that
is XML; REST/POX is&amp;nbsp;the simplest implementation. SOAP and the WS-* standards
elevate that model up to the distributed enterprise computing realm. 
&lt;/p&gt;
&lt;p&gt;
If you&amp;nbsp;compare the core properties of &lt;a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/"&gt;SOAP&lt;/a&gt;+&lt;a href="http://www.w3.org/TR/ws-addr-core/"&gt;WS-Adressing&lt;/a&gt; and
the &lt;a href="http://www.ietf.org/rfc/rfc2460.txt"&gt;Internet Protocol&lt;/a&gt; (IP) in an
interpretative fashion side-by-side and then also compare the &lt;a href="http://www.ietf.org/rfc/rfc793.txt"&gt;Transmission
Control Protocol&lt;/a&gt; (TCP)&amp;nbsp;to&amp;nbsp;&lt;a href="http://msdn.microsoft.com/ws/2005/02/ws-reliablemessaging/"&gt;WS-ReliableMessaging&lt;/a&gt;&amp;nbsp;it
may become quite clear to you what a fundamental abstraction above the networking
stacks and concrete technology coupling the WS-* specification family has become.
Every specification in the &lt;a href="http://msdn.microsoft.com/webservices/webservices/understanding/specs/default.aspx"&gt;long
list&lt;/a&gt; of WS-* specs is about converging and unifying formerly proprietary approaches
to messaging, security, transactions, metadata, management, business process management
and other aspects of distributed computing into this common platform.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Convergence&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
The beauty of that model is that it&amp;nbsp;is an implementation&amp;nbsp;superset of the
web. SOAP is the out-of-band metadata&amp;nbsp;container for&amp;nbsp;these abstractions.&amp;nbsp;The
key&amp;nbsp;feature of SOAP is SOAP:Header, which provides a standardized facility to
relay the required metadata alongside payloads. If you are willing to constrain out-of-band
metadata to one transport or application protocol, you don't need SOAP. 
&lt;/p&gt;
&lt;p&gt;
There is really very little difference between SOAP and REST/POX in terms of the information
model. SOAP carries headers and HTTP carries headers. In HTTP they are bolted to the
protocol layer and in SOAP they are tunneled through whatever carries the envelope.&amp;nbsp;[In
that sense, SOAP is calculated abuse of HTTP as a transport protocol for the purpose
of abstraction.] You can map WS-Addressing headers from and to HTTP headers. 
&lt;/p&gt;
&lt;p&gt;
The SOAP/WS-* model is richer, more flexible and more complex. The SOAP/WS-* set of
specifications is about infrastructure protocols. HTTP is an application protocol
and&amp;nbsp;therefore it is naturally more constrained - but has inherently defined qualities
and features that require an explicit protocol implementation in the SOAP/WS-* world;
one example is the inherent CRUD (create, read, update, delete) support in HTTP that
is matched by the explicitly composed-on-top WS-Transfer protocol in SOAP/WS-*
&lt;/p&gt;
&lt;p&gt;
The common platform is XML. You can scale down from SOAP/WS-* to REST/POX by putting
the naked payload on the wire and rely on HTTP for your metadata, error and status
information if that suits your needs. You can scale up from REST/POX to SOAP/WS-*
by encapsulating payloads and&amp;nbsp;leverage the WS-* infrastructure for&amp;nbsp;all the
flexibility and features it brings to the table. [It is fairly straightforward to
go from HTTP to SOAP/WS-*, and it is harder to go the other way. That's why I say
"superset".]
&lt;/p&gt;
&lt;p&gt;
Doing the right thing for a given scenario&amp;nbsp;is precisely what are enabling in
WCF.&amp;nbsp;There is a place for REST/POX for building the surface of the mashed and
faceless web and there is a place for SOAP for building the backbone of it - and some
may choose to mix and match these worlds. There are many scenarios and&amp;nbsp;architectural
models that suit them. What we want is 
&lt;/p&gt;
&lt;p align=center&gt;
&lt;strong&gt;One Way To Program&lt;/strong&gt;.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=1&gt;* REST=REpresentational State Transfer; POX="Plain-Old XML" or "simple
XML"&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,33c5fdc9-bb07-4c7b-bab7-9726a15c5b2c.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Talks/MIX06</category>
      <category>Technology</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=0fbf07a9-9e7a-4db4-a305-58250ac57a73</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,0fbf07a9-9e7a-4db4-a305-58250ac57a73.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,0fbf07a9-9e7a-4db4-a305-58250ac57a73.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=0fbf07a9-9e7a-4db4-a305-58250ac57a73</wfw:commentRss>
      <slash:comments>23</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
To (O/R) map or not to map.
</p>
        <p>
The monthly discussion about the benefits and dangers of O/R mapping is making rounds
on one of the mailing lists that I am signed up to. One big problem in this space
- from my experience of discussing this through with a lot of people over and over
– is that O/R mapping is one of those things where the sheer wish for an elegant solution
to the data/object schism obscures most of the rational argumentation. If an O/R mapper
provides a nice programming or tooling experience, developers (and architects) are
often willing to accept performance hits and a less-than-optimal tight coupling to
the data model, because they are lured by the aesthetics of the abstraction. 
</p>
        <p>
Another argument I keep hearing is that O/R mapping yields a significant productivity
boost. However, if that were the case and if using O/R mapping would shorten the average
development cost in a departmental development project by – say – a quarter or more,
O/R mapping would likely have taken over the world by now. It hasn't. And it's not
that the idea is new. It’s been around for well more than a decade.
</p>
        <p>
To me, O/R mapping is one of the unfortunate consequences of trying to apply OOP principles
to anything and everything. For "distributed objects", we’re fixing that with the
service orientation idea and the consequential constraints when we talk about the
network edge of applications. It turns out that the many of the same principles apply
to the database edge as well. The list below is just for giving you the idea. I could
write a whole article about this and I wish I had the time:
</p>
        <ul>
          <li>
Boundaries are explicit =&gt; Database access is explicit 
</li>
          <li>
Services avoid coupling (autonomy) =&gt; Database schema and in-process data
representation are disjoint and mapped explicitly</li>
          <li>
Share schema not code =&gt; Query/Sproc result sets and Sproc inputs form data
access schema (aliased result sets provide a degree of separation from phys. schema) 
</li>
        </ul>
        <p>
In short, I think the dream of transparent O/R mapping is the same dream that fueled
the development of fully transparent distributed objects in the early days of DSOM,
CORBA and (D)COM when we all thought that'd just work and were neglecting the related
issues of coupling, security, bandwidth, etc. 
</p>
        <p>
Meanwhile, we’ve learned the hard way that even though the idea was fantastic, it
was rather naïve to apply local development principles to distributed systems. The
same goes for database programming. Data is the most important thing in the vast majority
of applications. Every class of data items (table) surround special considerations:
read-only, read/write, insert-only; update frequency, currency and replicability;
access authorization; business relevance; caching strategies; etcetc.  
</p>
        <p>
          <strong>Proper data management is the key to great architecture.</strong> Ignoring
this and abstracting data access and data management away just to have a convenient
programming model is … problematic.
</p>
        <p>
And in closing: Many of the proponents of O/R mapping that I run into (and that is
a generalization and I am not trying to offend anyone – just an observation) are folks
who don't know SQL and RDBMS technology in any reasonable depth and/or often have
no interest in doing so. It may be worth exploring how tooling can better help the
SQL-challenged instead of obscuring all data access deep down in some framework and
make all data look like a bunch of local objects. If you have ideas, shoot. Comment
section is open for business.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=0fbf07a9-9e7a-4db4-a305-58250ac57a73" />
      </body>
      <title>The sirens are singing: O/R mapping </title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,0fbf07a9-9e7a-4db4-a305-58250ac57a73.aspx</guid>
      <link>http://vasters.com/clemensv/2006/03/07/The+Sirens+Are+Singing+OR+Mapping.aspx</link>
      <pubDate>Tue, 07 Mar 2006 11:17:47 GMT</pubDate>
      <description>&lt;p&gt;
To (O/R) map or not to map.
&lt;/p&gt;
&lt;p&gt;
The monthly discussion about the benefits and dangers of O/R mapping is making rounds
on one of the mailing lists that I am signed up to. One big problem in this space
- from my experience of discussing this through with a lot of people over and over
– is that O/R mapping is one of those things where the sheer wish for an elegant solution
to the data/object schism obscures most of the rational argumentation. If an O/R mapper
provides a nice programming or tooling experience, developers (and architects) are
often willing to accept performance hits and a less-than-optimal tight coupling to
the data model, because they are lured by the aesthetics of the abstraction. 
&lt;/p&gt;
&lt;p&gt;
Another argument I keep hearing is that O/R mapping yields a significant productivity
boost. However, if that were the case and if using O/R mapping would shorten the average
development cost in a departmental development project by – say – a quarter or more,
O/R mapping would likely have taken over the world by now. It hasn't. And it's not
that the idea is new. It’s been around for well more than a decade.
&lt;/p&gt;
&lt;p&gt;
To me, O/R mapping is one of the unfortunate consequences of trying to apply OOP principles
to anything and everything. For "distributed objects", we’re fixing that with the
service orientation idea and the consequential constraints when we talk about the
network edge of applications. It turns out that the many of the same principles apply
to the database edge as well. The list below is just for giving you the idea. I could
write a whole article about this and&amp;nbsp;I wish I had the time:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Boundaries are explicit&amp;nbsp;=&amp;gt; Database access is explicit 
&lt;/li&gt;
&lt;li&gt;
Services avoid coupling (autonomy)&amp;nbsp;=&amp;gt; Database schema and in-process data
representation are disjoint and mapped explicitly&lt;/li&gt;
&lt;li&gt;
Share schema not code&amp;nbsp;=&amp;gt; Query/Sproc result sets and Sproc inputs form data
access schema (aliased result sets provide a degree of separation from phys. schema) 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In short, I think the dream of transparent O/R mapping is the same dream that fueled
the development of fully transparent distributed objects in the early days of DSOM,
CORBA and (D)COM when we all thought that'd just work and were neglecting the related
issues of coupling, security, bandwidth, etc. 
&lt;/p&gt;
&lt;p&gt;
Meanwhile, we’ve learned the hard way that even though the idea was fantastic, it
was rather naïve to apply local development principles to distributed systems. The
same goes for database programming. Data is the most important thing in the vast majority
of applications. Every class of data items (table) surround special considerations:
read-only, read/write, insert-only; update frequency, currency and replicability;
access authorization; business relevance; caching strategies; etcetc.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Proper data management is the key to great architecture.&lt;/strong&gt; Ignoring
this and abstracting data access and data management away just to have a convenient
programming model is … problematic.
&lt;/p&gt;
&lt;p&gt;
And in closing: Many of the proponents of O/R mapping that I run into (and that is
a generalization and I am not trying to offend anyone – just an observation) are folks
who don't know SQL and RDBMS technology in any reasonable depth and/or often have
no interest in doing so. It may be worth exploring how tooling can better help the
SQL-challenged instead of obscuring all data access deep down in some framework and
make all data look like a bunch of local objects. If you have ideas, shoot. Comment
section is open for business.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=0fbf07a9-9e7a-4db4-a305-58250ac57a73" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,0fbf07a9-9e7a-4db4-a305-58250ac57a73.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=bafdbe41-0786-4a7f-a488-8ca447d612eb</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,bafdbe41-0786-4a7f-a488-8ca447d612eb.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,bafdbe41-0786-4a7f-a488-8ca447d612eb.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=bafdbe41-0786-4a7f-a488-8ca447d612eb</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <div class="Section1">
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">
              <a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=826bc7c9-8b0f-4df6-aabe-e6c5377a9446">See
Part 1</a>
            </span>
          </p>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">Before we can do anything about
deadlocks or deal with similar troubles, we first need to be able to tell that we
indeed have a deadlock situation. Finding this out is a matter of knowing the respective
error codes that your database gives you and a mechanism to bubble that information
up to some code that will handle the situation. So before we can think about and write
the handling logic for failed/failing but safely repeatable transactions, we need
to build a few little things. The first thing we’ll need is an exception class
that will wrap the original exception indicating the reason for the transaction failure.
The new exception class’s identity will later serve to filter out exceptions
in a “catch” statement and take the appropriate actions.</span>
          </p>
          <table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #e6e6e6; BORDER-LEFT: medium none; WIDTH: 100%; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" width="100%" border="1">
            <tbody>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top">
                  <p class="MsoNormal">
                    <span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'">using</span>
                    <span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Lucida Console'"> System;<br /><span style="COLOR: blue">using</span> System.Runtime.Serialization;<br /><br /><span style="COLOR: blue">namespace</span> newtelligence.EnterpriseTools.Data<br />
{<br />
   [Serializable]<br />
   <span style="COLOR: blue">public</span><span style="COLOR: blue">class</span> RepeatableOperationException
: Exception<br />
   {<br />
       <span style="COLOR: blue">public</span> RepeatableOperationException():<span style="COLOR: blue">base</span>()<br />
       {<br />
       }<br /><br />
       <span style="COLOR: blue">public</span> RepeatableOperationException(Exception
innerException)<br />
           :<span style="COLOR: blue">base</span>(<span style="COLOR: blue">null</span>,innerException)<br />
       {<br />
       }<br /><br />
       <span style="COLOR: blue">public</span> RepeatableOperationException(<span style="COLOR: blue">string</span> message,
Exception innerException)<br />
           :<span style="COLOR: blue">base</span>(message,innerException)<br />
       {<br />
       }<br /><br />
       <span style="COLOR: blue">public</span> RepeatableOperationException(<span style="COLOR: blue">string</span> message):<span style="COLOR: blue">base</span>(message)<br />
       {<br />
       }<br /><br />
        <span style="COLOR: blue">public</span> RepeatableOperationException(<br />
          SerializationInfo serializationInfo, 
<br />
          StreamingContext streamingContext)<br />
            :<span style="COLOR: blue">base</span>(serializationInfo,streamingContext)<br />
        {<br />
        }<br /><br />
        <span style="COLOR: blue">public</span><span style="COLOR: blue">override</span><span style="COLOR: blue">void</span> GetObjectData(<br />
           System.Runtime.Serialization.SerializationInfo
info,<br />
           System.Runtime.Serialization.StreamingContext
context)<br />
        {<br />
            <span style="COLOR: blue">base</span>.GetObjectData
(info, context);<br />
        }<br />
   }<br />
}</span>
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">Having an exception wrapper with
the desired semantics, we know need to be able to figure out when to replace the original
exception with this wrapper and re-throw it up on the call stack. The idea is that
whenever you execute a database operation – or, more generally, any operation
that might be repeatable on failure – you will catch the resulting exception
and run it through a factory, which will analyze the exception and wrap it with the
RepeatableOperationException if the issue at hand can be resolved by re-running the
transaction. The (still a little naïve) code below illustrates how to such a
factory in the application code. Later we will flesh out the catch block a little
more, since we will lose the original call stack if we end up re-throwing the original
exception like shown here:</span>
          </p>
          <table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #e6e6e6; BORDER-LEFT: medium none; WIDTH: 100%; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" width="100%" border="1">
            <tbody>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top">
                  <p class="MsoNormal">
                    <span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'">Try<br /></span>
                    <span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Lucida Console'">{<br />
   dbConnection.Open();<br />
   sprocUpdateAndQueryStuff.Parameters["@StuffArgument"].Value = argument;<br />
   result = <span style="COLOR: blue">this</span>.GetResultFromReader( sprocUpdateAndQueryStuff.ExecuteReader()
);<br />
}<br /><span style="COLOR: blue">catch</span>( Exception exception )<br />
{<br /><span style="COLOR: blue">   throw</span> RepeatableOperationExceptionMapper.MapException(
exception );                   
        
<br />
}<br /><span style="COLOR: blue">finally<br /></span>{<br />
   dbConnection.Close();<br />
}</span>
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">The factory class itself is rather
simple in structure, but a bit tricky to put together, because you have to know the
right error codes for all resource managers you will ever run into. In the example
below I put in what I believe to be the appropriate codes for SQL Server and Oracle
(corrections are welcome) and left the ODBC and OLE DB factories (for which would
have to inspect the driver type and the respective driver-specific error codes) blank.
The factory will check out the exception data type and delegate mapping to a private
method that is specialized for a specific managed provider. </span>
          </p>
          <table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #e6e6e6; BORDER-LEFT: medium none; WIDTH: 100%; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" width="100%" border="1">
            <tbody>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top">
                  <p class="MsoNormal">
                    <span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'">using</span>
                    <span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Lucida Console'"> System;<br /><span style="COLOR: blue">using</span> System.Data.SqlClient;<br /><span style="COLOR: blue">using</span> System.Data.OleDb;<br /><span style="COLOR: blue">using</span> System.Data.Odbc;<br /><span style="COLOR: blue">using</span> System.Data.OracleClient;<br /><br /><span style="COLOR: blue">namespace</span> newtelligence.EnterpriseTools.Data<br />
{<br />
   <span style="COLOR: blue">public</span><span style="COLOR: blue">class</span> RepeatableOperationExceptionMapper<br />
   {<br />
        <span style="COLOR: gray">///</span><span style="COLOR: green"></span><span style="COLOR: gray">&lt;summary&gt;<br /></span>        <span style="COLOR: gray">///</span><span style="COLOR: green"> Maps
the exception to a Repeatable exception, if the error code<br /></span>        <span style="COLOR: gray">///</span><span style="COLOR: green"> indicates
that the transaction is repeatable.<br /></span>        <span style="COLOR: gray">///</span><span style="COLOR: green"></span><span style="COLOR: gray">&lt;/summary&gt;<br /></span>        <span style="COLOR: gray">///</span><span style="COLOR: green"></span><span style="COLOR: gray">&lt;param
name="sqlException"&gt;&lt;/param&gt;<br /></span>        <span style="COLOR: gray">///</span><span style="COLOR: green"></span><span style="COLOR: gray">&lt;returns&gt;&lt;/returns&gt;<br /></span>        <span style="COLOR: blue">private</span><span style="COLOR: blue">static</span> Exception
MapSqlException( SqlException sqlException )<br />
        {<br />
            <span style="COLOR: blue">switch</span> (
sqlException.Number )<br />
            {<br />
                <span style="COLOR: blue">case</span> -2: <span style="COLOR: green">/*
Client Timeout */</span><br />
                <span style="COLOR: blue">case</span> 701: <span style="COLOR: green">/*
Out of Memory */</span><br />
                <span style="COLOR: blue">case</span> 1204: <span style="COLOR: green">/*
Lock Issue */</span><br />
                <span style="COLOR: blue">case</span> 1205: <span style="COLOR: green">/*
Deadlock Victim */</span><br />
                <span style="COLOR: blue">case</span> 1222: <span style="COLOR: green">/*
Lock Request Timeout */</span><br />
                <span style="COLOR: blue">case</span> 8645: <span style="COLOR: green">/*
Timeout waiting for memory resource */</span><br />
                <span style="COLOR: blue">case</span> 8651: <span style="COLOR: green">/*
Low memory condition */</span><br />
                    <span style="COLOR: blue">return</span><span style="COLOR: blue">new</span> RepeatableOperationException(sqlException);<br />
                <span style="COLOR: blue">default</span>:<br />
                    <span style="COLOR: blue">return</span> sqlException;<br />
            }<br />
        }<br /><br />
        <span style="COLOR: blue">private</span><span style="COLOR: blue">static</span> Exception
MapOleDbException( OleDbException oledbException )<br />
        {<br />
            <span style="COLOR: blue">switch</span> (
oledbException.ErrorCode )<br />
            {<br />
                <span style="COLOR: blue">default</span>:<br />
                    <span style="COLOR: blue">return</span> oledbException;<br />
            }<br />
        }<br /><br />
        <span style="COLOR: blue">private</span><span style="COLOR: blue">static</span> Exception
MapOdbcException( OdbcException odbcException )<br />
        {<br />
            <span style="COLOR: blue">return</span> odbcException;            
<br />
        }<br /><br />
        <span style="COLOR: blue">private</span><span style="COLOR: blue">static</span> Exception
MapOracleException( OracleException oracleException )<br />
        {<br />
            <span style="COLOR: blue">switch</span> (
oracleException.Code )<br />
            {<br />
                <span style="COLOR: blue">case</span> 104:  <span style="COLOR: green">/*
ORA-00104: Deadlock detected; all public servers blocked waiting for resources */<br /></span>                <span style="COLOR: blue">case</span> 1013: <span style="COLOR: green">/*
ORA-01013: User requested cancel of current operation */<br /></span>                <span style="COLOR: blue">case</span> 2087: <span style="COLOR: green">/*
ORA-02087: Object locked by another process in same transaction */<br /></span>                <span style="COLOR: blue">case</span> 60:   <span style="COLOR: green">/*
ORA-00060: Deadlock detected while waiting for resource */</span><br />
              
     <span style="COLOR: blue">return</span><span style="COLOR: blue">new</span> RepeatableOperationException(
oracleException );<br />
                <span style="COLOR: blue">default</span>:<br />
                    <span style="COLOR: blue">return</span> oracleException;<br />
            }<br />
        }<br /><br />
        <span style="COLOR: blue">public</span><span style="COLOR: blue">static</span> Exception
MapException( Exception exception )<br />
        {<br />
            <span style="COLOR: blue">if</span> (
exception <span style="COLOR: blue">is</span> SqlException )<br />
            {<br />
                <span style="COLOR: blue">return</span> MapSqlException(
exception <span style="COLOR: blue">as</span> SqlException );<br />
            }<br />
            <span style="COLOR: blue">else</span><span style="COLOR: blue">if</span> (
exception <span style="COLOR: blue">is</span> OleDbException )<br />
            {<br />
                <span style="COLOR: blue">return</span> MapOleDbException(
exception <span style="COLOR: blue">as</span> OleDbException );<br />
            }<br />
            <span style="COLOR: blue">else</span><span style="COLOR: blue">if</span> (exception <span style="COLOR: blue">is</span> OdbcException
)<br />
            {<br />
                <span style="COLOR: blue">return</span> MapOdbcException(
exception <span style="COLOR: blue">as</span> OdbcException );<br />
            }<br />
            <span style="COLOR: blue">else</span><span style="COLOR: blue">if</span> (exception <span style="COLOR: blue">is</span> OracleException
)<br />
            {<br />
                <span style="COLOR: blue">return</span> MapOracleException(
exception <span style="COLOR: blue">as</span> OracleException );<br />
            }<br />
            <span style="COLOR: blue">else</span><br />
            {<br />
                <span style="COLOR: blue">return</span> exception;<br />
            }<br />
        }<br />
   }<br />
}<br /><br /></span>
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">With that little framework of two
classes, we can now selectively throw exceptions that convey whether a failed/failing
transaction is worth repeating. Next step: How do we do actually run such repeats
and make sure we neither lose data nor make the user unhappy in the process? Stay
tuned.</span>
          </p>
        </div>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=bafdbe41-0786-4a7f-a488-8ca447d612eb" />
      </body>
      <title>Dealing with Deadlocks and Other Unfortunate Events on the Application Level: Part 2</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,bafdbe41-0786-4a7f-a488-8ca447d612eb.aspx</guid>
      <link>http://vasters.com/clemensv/2004/11/30/Dealing+With+Deadlocks+And+Other+Unfortunate+Events+On+The+Application+Level+Part+2.aspx</link>
      <pubDate>Tue, 30 Nov 2004 11:02:27 GMT</pubDate>
      <description>&lt;div class=Section1&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;&lt;a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=826bc7c9-8b0f-4df6-aabe-e6c5377a9446"&gt;See
Part 1&lt;/a&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;Before we can do anything about
deadlocks or deal with similar troubles, we first need to be able to tell that we
indeed have a deadlock situation. Finding this out is a matter of knowing the respective
error codes that your database gives you and a mechanism to bubble that information
up to some code that will handle the situation. So before we can think about and write
the handling logic for failed/failing but safely repeatable transactions, we need
to build a few little things. The first thing we&amp;#8217;ll need is an exception class
that will wrap the original exception indicating the reason for the transaction failure.
The new exception class&amp;#8217;s identity will later serve to filter out exceptions
in a &amp;#8220;catch&amp;#8221; statement and take the appropriate actions.&lt;/span&gt;
&lt;/p&gt;
&lt;table class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #e6e6e6; BORDER-LEFT: medium none; WIDTH: 100%; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing=0 cellpadding=0 width="100%" border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'"&gt;using&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Lucida Console'"&gt; System;&lt;br&gt;
&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Runtime.Serialization;&lt;br&gt;
&lt;br&gt;
&lt;span style="COLOR: blue"&gt;namespace&lt;/span&gt; newtelligence.EnterpriseTools.Data&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; [Serializable]&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;class&lt;/span&gt; RepeatableOperationException
: Exception&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; RepeatableOperationException():&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; RepeatableOperationException(Exception
innerException)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;:&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;(&lt;span style="COLOR: blue"&gt;null&lt;/span&gt;,innerException)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt; RepeatableOperationException(&lt;span style="COLOR: blue"&gt;string&lt;/span&gt; message,
Exception innerException)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;(message,innerException)&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; RepeatableOperationException(&lt;span style="COLOR: blue"&gt;string&lt;/span&gt; message):&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;(message)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; RepeatableOperationException(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SerializationInfo serializationInfo, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StreamingContext streamingContext)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;(serializationInfo,streamingContext)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;override&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; GetObjectData(&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Runtime.Serialization.SerializationInfo
info,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Runtime.Serialization.StreamingContext
context)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;base&lt;/span&gt;.GetObjectData
(info, context);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;Having an exception wrapper with
the desired semantics, we know need to be able to figure out when to replace the original
exception with this wrapper and re-throw it up on the call stack. The idea is that
whenever you execute a database operation &amp;#8211; or, more generally, any operation
that might be repeatable on failure &amp;#8211; you will catch the resulting exception
and run it through a factory, which will analyze the exception and wrap it with the
RepeatableOperationException if the issue at hand can be resolved by re-running the
transaction. The (still a little na&amp;#239;ve) code below illustrates how to such a
factory in the application code. Later we will flesh out the catch block a little
more, since we will lose the original call stack if we end up re-throwing the original
exception like shown here:&lt;/span&gt;
&lt;/p&gt;
&lt;table class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #e6e6e6; BORDER-LEFT: medium none; WIDTH: 100%; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing=0 cellpadding=0 width="100%" border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'"&gt;Try&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Lucida Console'"&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp; dbConnection.Open();&lt;br&gt;
&amp;nbsp; &amp;nbsp;sprocUpdateAndQueryStuff.Parameters["@StuffArgument"].Value = argument;&lt;br&gt;
&amp;nbsp;&amp;nbsp; result = &lt;span style="COLOR: blue"&gt;this&lt;/span&gt;.GetResultFromReader( sprocUpdateAndQueryStuff.ExecuteReader()
);&lt;br&gt;
}&lt;br&gt;
&lt;span style="COLOR: blue"&gt;catch&lt;/span&gt;( Exception exception )&lt;br&gt;
{&lt;br&gt;
&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp; throw&lt;/span&gt; RepeatableOperationExceptionMapper.MapException(
exception );&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; 
&lt;br&gt;
}&lt;br&gt;
&lt;span style="COLOR: blue"&gt;finally&lt;br&gt;
&lt;/span&gt;{&lt;br&gt;
&amp;nbsp; &amp;nbsp;dbConnection.Close();&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;The factory class itself is rather
simple in structure, but a bit tricky to put together, because you have to know the
right error codes for all resource managers you will ever run into. In the example
below I put in what I believe to be the appropriate codes for SQL Server and Oracle
(corrections are welcome) and left the ODBC and OLE DB factories (for which would
have to inspect the driver type and the respective driver-specific error codes) blank.
The factory will check out the exception data type and delegate mapping to a private
method that is specialized for a specific managed provider. &lt;/span&gt;
&lt;/p&gt;
&lt;table class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #e6e6e6; BORDER-LEFT: medium none; WIDTH: 100%; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing=0 cellpadding=0 width="100%" border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'"&gt;using&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Lucida Console'"&gt; System;&lt;br&gt;
&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Data.SqlClient;&lt;br&gt;
&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Data.OleDb;&lt;br&gt;
&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Data.Odbc;&lt;br&gt;
&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Data.OracleClient;&lt;br&gt;
&lt;br&gt;
&lt;span style="COLOR: blue"&gt;namespace&lt;/span&gt; newtelligence.EnterpriseTools.Data&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;class&lt;/span&gt; RepeatableOperationExceptionMapper&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Maps
the exception to a Repeatable exception, if the error code&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; indicates
that the transaction is repeatable.&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;param
name="sqlException"&amp;gt;&amp;lt;/param&amp;gt;&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; Exception
MapSqlException( SqlException sqlException )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;switch&lt;/span&gt; (
sqlException.Number )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; -2: &lt;span style="COLOR: green"&gt;/*
Client Timeout */&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 701: &lt;span style="COLOR: green"&gt;/*
Out of Memory */&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 1204: &lt;span style="COLOR: green"&gt;/*
Lock Issue */&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 1205: &lt;span style="COLOR: green"&gt;/*
Deadlock Victim */&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 1222: &lt;span style="COLOR: green"&gt;/*
Lock Request Timeout */&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 8645: &lt;span style="COLOR: green"&gt;/*
Timeout waiting for memory resource */&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 8651: &lt;span style="COLOR: green"&gt;/*
Low memory condition */&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; RepeatableOperationException(sqlException);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;default&lt;/span&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; sqlException;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; Exception
MapOleDbException( OleDbException oledbException )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;switch&lt;/span&gt; (
oledbException.ErrorCode )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="COLOR: blue"&gt;default&lt;/span&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; oledbException;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; Exception
MapOdbcException( OdbcException odbcException )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; odbcException;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; Exception
MapOracleException( OracleException oracleException )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;switch&lt;/span&gt; (
oracleException.Code )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 104:&amp;nbsp; &lt;span style="COLOR: green"&gt;/*
ORA-00104: Deadlock detected; all public servers blocked waiting for resources */&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 1013: &lt;span style="COLOR: green"&gt;/*
ORA-01013: User requested cancel of current operation */&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 2087: &lt;span style="COLOR: green"&gt;/*
ORA-02087: Object locked by another process in same transaction */&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; 60:&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;/*
ORA-00060: Deadlock detected while waiting for resource */&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="COLOR: blue"&gt;return&lt;/span&gt; &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; RepeatableOperationException(
oracleException );&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;default&lt;/span&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; oracleException;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; Exception
MapException( Exception exception )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (
exception &lt;span style="COLOR: blue"&gt;is&lt;/span&gt; SqlException )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; MapSqlException(
exception &lt;span style="COLOR: blue"&gt;as&lt;/span&gt; SqlException );&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;else&lt;/span&gt; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (
exception &lt;span style="COLOR: blue"&gt;is&lt;/span&gt; OleDbException )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; MapOleDbException(
exception &lt;span style="COLOR: blue"&gt;as&lt;/span&gt; OleDbException );&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;else&lt;/span&gt; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (exception &lt;span style="COLOR: blue"&gt;is&lt;/span&gt; OdbcException
)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; MapOdbcException(
exception &lt;span style="COLOR: blue"&gt;as&lt;/span&gt; OdbcException );&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;else&lt;/span&gt; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (exception &lt;span style="COLOR: blue"&gt;is&lt;/span&gt; OracleException
)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; MapOracleException(
exception &lt;span style="COLOR: blue"&gt;as&lt;/span&gt; OracleException );&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;else&lt;/span&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; exception;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;With that little framework of two
classes, we can now selectively throw exceptions that convey whether a failed/failing
transaction is worth repeating. Next step: How do we do actually run such repeats
and make sure we neither lose data nor make the user unhappy in the process? Stay
tuned.&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=bafdbe41-0786-4a7f-a488-8ca447d612eb" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,bafdbe41-0786-4a7f-a488-8ca447d612eb.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology/Enterprise Services</category>
      <category>Technology/MSMQ</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=826bc7c9-8b0f-4df6-aabe-e6c5377a9446</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,826bc7c9-8b0f-4df6-aabe-e6c5377a9446.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,826bc7c9-8b0f-4df6-aabe-e6c5377a9446.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=826bc7c9-8b0f-4df6-aabe-e6c5377a9446</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <div class="Section1">
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">Deadlocks and other locking conflicts
that cause transactional database operations to fail are things that puzzle many application
developers. Sure, proper database design and careful implementation of database access
(and appropriate support by the database engine) <i>should</i> take care of that problem,
but it cannot do so in all cases. Sometimes, especially under stress and other situations
with high lock contention, a database just has not much of a choice but picking at
least one of the transactions competing for the same locks as the victim in resolving
the deadlock situation and then aborts the chosen transaction. Generally speaking,
transactions that abort and roll back are a good thing, because this behavior guarantees
data integrity. In the end, we use transaction technology for those cases where data
integrity is at risk. What’s interesting is that even though transactions are
a technology that is explicitly about things going wrong, the strategy for dealing
with failing transaction is often not much more than to bubble the problem up to the
user and say “We apologize for the inconvenience. Please press OK”.</span>
          </p>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">The appropriate strategy for handling
a deadlock or some other recoverable reason for a transaction abort on the application
level is to back out of the entire operation and to retry the transaction. Retrying
is a gamble that the next time the transaction runs, it won’t run into the same
deadlock situation again or that it will at least come out victorious when the database
picks its victims. Eventually, it’ll work. Even if it takes a few attempts.
That’s the idea. It’s quite simple.</span>
          </p>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">What is not really all that simple
is the implementation. Whenever you are using transactions, you must make your code
aware that such “good errors” may occur at any time. Wrapping your transactional
ODBC/OLEDB/ADO/ADO.NET code or calls to transactional Enterprise Services or COM+
components with a try/catch block, writing errors to log-files and showing message
boxes to users just isn’t the right thing to do. The right thing is to simply
do the same batch of work again and until it succeeds.</span>
          </p>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">The problem that some developers
seem to have with “just retry” is that it’s not so clear what should
be retried. It’s a problem of finding and defining the proper transaction scope.
Especially when user interaction is in the picture, things easily get very confusing.
If a user has filled in a form on a web page or some dialog window and all of his/her
input is complete and correct, should the user be bothered with a message that the
update transaction failed due to a locking issue? Certainly not. Should the user know
when the transaction fails because the database is currently unavailable? Maybe, but
not necessarily. Should the user be made aware that the application he/she is using
is for some sudden reason incompatible with the database schema of the backend database?
Maybe, but what does Joe in the sales department do with that valuable piece of information?</span>
          </p>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">If stuff fails, should we just
forget about Joe’s input and tell him to come back when the system is happier
to serve him? So, in other words, do we have Joe retry the job? That’s easy
to program, but that sort of strategy doesn’t really make Joe happy, does it? </span>
          </p>
          <p class="MsoNormal">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma">So what’s the right thing
to do? One part of the solution is a proper separation between the things the user
(or a program) does and the things that the transaction does. This will give us two
layers and “a job” that can be handed down from the presentation layer
down to the “transaction layer”. Once this separation is in place, we
can come up with a mechanism that will run those jobs in transactions and will automate
how and when transactions are to be retried. Transactional MSMQ queues turn out to
be a brilliant tool to make this very easy to implement. More tomorrow. Stay tuned.</span>
          </p>
        </div>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=826bc7c9-8b0f-4df6-aabe-e6c5377a9446" />
      </body>
      <title>Dealing with Deadlocks and Other Unfortunate Events on the Application Level: Part 1</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,826bc7c9-8b0f-4df6-aabe-e6c5377a9446.aspx</guid>
      <link>http://vasters.com/clemensv/2004/11/29/Dealing+With+Deadlocks+And+Other+Unfortunate+Events+On+The+Application+Level+Part+1.aspx</link>
      <pubDate>Mon, 29 Nov 2004 23:26:11 GMT</pubDate>
      <description>&lt;div class=Section1&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;Deadlocks and other locking conflicts
that cause transactional database operations to fail are things that puzzle many application
developers. Sure, proper database design and careful implementation of database access
(and appropriate support by the database engine) &lt;i&gt;should&lt;/i&gt; take care of that problem,
but it cannot do so in all cases. Sometimes, especially under stress and other situations
with high lock contention, a database just has not much of a choice but picking at
least one of the transactions competing for the same locks as the victim in resolving
the deadlock situation and then aborts the chosen transaction. Generally speaking,
transactions that abort and roll back are a good thing, because this behavior guarantees
data integrity. In the end, we use transaction technology for those cases where data
integrity is at risk. What&amp;#8217;s interesting is that even though transactions are
a technology that is explicitly about things going wrong, the strategy for dealing
with failing transaction is often not much more than to bubble the problem up to the
user and say &amp;#8220;We apologize for the inconvenience. Please press OK&amp;#8221;.&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;The appropriate strategy for handling
a deadlock or some other recoverable reason for a transaction abort on the application
level is to back out of the entire operation and to retry the transaction. Retrying
is a gamble that the next time the transaction runs, it won&amp;#8217;t run into the same
deadlock situation again or that it will at least come out victorious when the database
picks its victims. Eventually, it&amp;#8217;ll work. Even if it takes a few attempts.
That&amp;#8217;s the idea. It&amp;#8217;s quite simple.&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;What is not really all that simple
is the implementation. Whenever you are using transactions, you must make your code
aware that such &amp;#8220;good errors&amp;#8221; may occur at any time. Wrapping your transactional
ODBC/OLEDB/ADO/ADO.NET code or calls to transactional Enterprise Services or COM+
components with a try/catch block, writing errors to log-files and showing message
boxes to users just isn&amp;#8217;t the right thing to do. The right thing is to simply
do the same batch of work again and until it succeeds.&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;The problem that some developers
seem to have with &amp;#8220;just retry&amp;#8221; is that it&amp;#8217;s not so clear what should
be retried. It&amp;#8217;s a problem of finding and defining the proper transaction scope.
Especially when user interaction is in the picture, things easily get very confusing.
If a user has filled in a form on a web page or some dialog window and all of his/her
input is complete and correct, should the user be bothered with a message that the
update transaction failed due to a locking issue? Certainly not. Should the user know
when the transaction fails because the database is currently unavailable? Maybe, but
not necessarily. Should the user be made aware that the application he/she is using
is for some sudden reason incompatible with the database schema of the backend database?
Maybe, but what does Joe in the sales department do with that valuable piece of information?&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;If stuff fails, should we just
forget about Joe&amp;#8217;s input and tell him to come back when the system is happier
to serve him? So, in other words, do we have Joe retry the job? That&amp;#8217;s easy
to program, but that sort of strategy doesn&amp;#8217;t really make Joe happy, does it? &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma"&gt;So what&amp;#8217;s the right thing
to do? One part of the solution is a proper separation between the things the user
(or a program) does and the things that the transaction does. This will give us two
layers and &amp;#8220;a job&amp;#8221; that can be handed down from the presentation layer
down to the &amp;#8220;transaction layer&amp;#8221;. Once this separation is in place, we
can come up with a mechanism that will run those jobs in transactions and will automate
how and when transactions are to be retried. Transactional MSMQ queues turn out to
be a brilliant tool to make this very easy to implement. More tomorrow. Stay tuned.&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=826bc7c9-8b0f-4df6-aabe-e6c5377a9446" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,826bc7c9-8b0f-4df6-aabe-e6c5377a9446.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology/Enterprise Services</category>
      <category>Technology/MSMQ</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=2b90ceed-5814-4088-b76e-eca029664fdc</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,2b90ceed-5814-4088-b76e-eca029664fdc.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,2b90ceed-5814-4088-b76e-eca029664fdc.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=2b90ceed-5814-4088-b76e-eca029664fdc</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I am presently doing some intense research on services, service patterns, message
exchange patterns and many other issues related to services (No surprise there). However,
I can't do that without external help and since many people are reading my blog, I
can just as well start asking around right here: 
</p>
        <p>
I would like to get in touch with companies (preferrably insurances and
banks) who afford a corporate history department. The ambitious goal I have is to reconstruct
a few banking or insurance or purchasing business processes of ca. 1955-1965.
I have come to believe that there is a lot, a lot to be learned there that will be
very useful to what we're all doing. The deal is that if you share, I share whatever
I have as soon as I have it. My contact address is <a href="mailto:clemensv@newtelligence.com">clemensv@newtelligence.com</a></p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=2b90ceed-5814-4088-b76e-eca029664fdc" />
      </body>
      <title>Call for Help on History Lessons about Services</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,2b90ceed-5814-4088-b76e-eca029664fdc.aspx</guid>
      <link>http://vasters.com/clemensv/2004/11/20/Call+For+Help+On+History+Lessons+About+Services.aspx</link>
      <pubDate>Sat, 20 Nov 2004 19:05:20 GMT</pubDate>
      <description>&lt;p&gt;
I am presently doing some intense research on services, service patterns, message
exchange patterns and many other issues related to services (No surprise there). However,
I can't do that without external help and since many people are reading my blog, I
can just as well start asking around right here: 
&lt;/p&gt;
&lt;p&gt;
I would like to get in touch&amp;nbsp;with&amp;nbsp;companies (preferrably insurances and
banks) who afford a corporate history department. The ambitious goal I have is to&amp;nbsp;reconstruct
a few&amp;nbsp;banking or insurance or purchasing business processes of ca. 1955-1965.
I have come to believe that there is a lot, a lot to be learned there that will be
very useful to what we're all doing. The deal is that if you share, I share whatever
I have as soon as I have it. My contact address is &lt;a href="mailto:clemensv@newtelligence.com"&gt;clemensv@newtelligence.com&lt;/a&gt; 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=2b90ceed-5814-4088-b76e-eca029664fdc" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,2b90ceed-5814-4088-b76e-eca029664fdc.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=b90c9c1c-131f-4806-bf29-8540b40cd8ec</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,b90c9c1c-131f-4806-bf29-8540b40cd8ec.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,b90c9c1c-131f-4806-bf29-8540b40cd8ec.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=b90c9c1c-131f-4806-bf29-8540b40cd8ec</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I get emails like that very frequently. I have some news.
</p>
        <p>
Short story: Microsoft is still willing and working to publish the application
that I presented at TechEd Europe (see <a href="http://benjaminm.net/PermaLink.aspx?guid=87ce6b8b-0fbf-4f0d-86c9-d9e780a1cb6a">Benjamin's
report</a>) and they keep telling me that it will come out. Apparently there
is a lot of consensus building to be done to get a big sample application out
of the door. So there's nothing to be found on msdn, yet.
</p>
        <p>
Little known secret: There are 15 lucky indivduals who have already received
(hand-delivered) the Proseware code as a technical preview under a non-disclosure
agreement. Because we (newtelligence) designed and wrote the sample application,
we have permission to distribute the complete sample to participants of our <a href="http://www.newtelligence.net/PermaLink.aspx?guid=c9fd0897-8702-4e1b-8aa9-2dbcf66051b4">SOA
workshops</a> and seminars. 
</p>
        <p>
So if you want to get yours hands on it, all you need to do is to send mail to <a href="mailto:training@newtelligence.com">training@newtelligence.com</a> to
sign up for one of the public events [Next published date is Dec 1-3, and
the event is held in German, unless we get swamped with international inquiries] or
you send email to the same address asking for an on-site workshop delivery. At
this time, we (and MS) bind the code sample to workshop attendance so that you really
understand why the application was built like it's built and that you fully understand
the guidance that the application implicitly and explicitly carries (and doesn't carry).
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b90c9c1c-131f-4806-bf29-8540b40cd8ec" />
      </body>
      <title>"Clemens, what happened to Proseware?"</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,b90c9c1c-131f-4806-bf29-8540b40cd8ec.aspx</guid>
      <link>http://vasters.com/clemensv/2004/10/28/Clemens+What+Happened+To+Proseware.aspx</link>
      <pubDate>Thu, 28 Oct 2004 11:33:24 GMT</pubDate>
      <description>&lt;p&gt;
I get emails like that very frequently. I have some news.
&lt;/p&gt;
&lt;p&gt;
Short story: Microsoft is still willing and working to publish&amp;nbsp;the application
that I presented at TechEd Europe&amp;nbsp;(see &lt;a href="http://benjaminm.net/PermaLink.aspx?guid=87ce6b8b-0fbf-4f0d-86c9-d9e780a1cb6a"&gt;Benjamin's
report&lt;/a&gt;) and&amp;nbsp;they&amp;nbsp;keep&amp;nbsp;telling me that it&amp;nbsp;will come out. Apparently&amp;nbsp;there
is a lot of consensus building to be done&amp;nbsp;to get a big sample application out
of the door. So there's nothing to be found on msdn, yet.
&lt;/p&gt;
&lt;p&gt;
Little known secret: There are 15 lucky indivduals&amp;nbsp;who have already received
(hand-delivered) the Proseware&amp;nbsp;code as a technical preview under a non-disclosure
agreement.&amp;nbsp;Because we (newtelligence) designed and wrote the sample application,
we have permission to distribute the&amp;nbsp;complete sample to participants of our &lt;a href="http://www.newtelligence.net/PermaLink.aspx?guid=c9fd0897-8702-4e1b-8aa9-2dbcf66051b4"&gt;SOA
workshops&lt;/a&gt; and seminars. 
&lt;/p&gt;
&lt;p&gt;
So if you want to get yours hands on it, all you need to do is to send mail to &lt;a href="mailto:training@newtelligence.com"&gt;training@newtelligence.com&lt;/a&gt; to
sign up&amp;nbsp;for one of the public events [Next published date is&amp;nbsp;Dec 1-3, and
the event is held in German, unless we get swamped with international inquiries] or
you send email to the same address asking&amp;nbsp;for an on-site workshop delivery. At
this time, we (and MS) bind the code sample to workshop attendance so that you really
understand why the application&amp;nbsp;was built like it's built and that you fully understand
the guidance that the application implicitly and explicitly carries (and doesn't carry).
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b90c9c1c-131f-4806-bf29-8540b40cd8ec" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,b90c9c1c-131f-4806-bf29-8540b40cd8ec.aspx</comments>
      <category>Architecture/SOA</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=1fdd514d-cf1f-4350-a9b3-42cf8faa1740</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,1fdd514d-cf1f-4350-a9b3-42cf8faa1740.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,1fdd514d-cf1f-4350-a9b3-42cf8faa1740.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=1fdd514d-cf1f-4350-a9b3-42cf8faa1740</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I feel like I have been "out of business" for a really long time and like I really
got nothing done in the past 3 months, even though that's objectively not true. I
guess that's "conference &amp; travel withdrawal", because I had tone and tons of
bigger events in the first half of the year and 3 smaller events since TechEd Amsterdam
in July. On the upside, I am pretty relaxed and have certainly reduced
my stress-related health risks ;-)
</p>
        <p>
So with winter and its short days coming up, the other half of my life living a 1/3
around the planet until next spring, I can and am going to spend some serious time
on a bunch of things: 
</p>
        <p>
On the <em>new programming stuff</em> front: 
<br />
     Catch up on what has been going on in Indigo in recent months,
dig deeper into "everything Whidbey", figure out the CLR aspects of SQL
2005 and familiarize myself with VS Team System.
</p>
        <p>
On the <em>existing programming stuff</em> front: 
<br />
      Consolidate my "e:\development\*"  directory on my
harddrive and pull together all my samples and utilities for Enterprise
Services, ASP.NET Web Services and other enterprise-development technologies and
create a production-quality library from of them for us and our customers to
use. Also, because the Indigo team is doing quite a bit of COM/COM+ replumbing
recently in order to have that prohgraming model ride on Indigo, I have some
hope that I can now file bugs/wishes against COM+ that might have a chance of
being addressed. If that happens and a particular showstopper is getting
out of the way, I will reopen this <a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=110">project
here</a> and will, at the very least, release it as a toy.
</p>
        <p>
On the <em>architectural stuff</em> front:<br />
         Refine our SOA Workshop material, do
quite a bit of additional work on the FABRIQ, evolve the Proseware architecture model,
and get some pending projects done. In addition to our own SOA workshops (the
next English-language workshop is held <a href="http://www.newtelligence.net/PermaLink.aspx?guid=245f5632-1ea1-4e0a-acd7-718cab67d3ab">December
1-3, 2004 in Düsseldorf</a>), there will be a series of invite-only Microsoft
events on Service Orientation throughout Europe this fall/winter, and I am very
happy that I will be speaking -- mostly on architecture topics -- at the Microsoft
Eastern Mediterranean Developer Conference in Amman/Jordan in November and several
other locations in the Middle East early next year. 
</p>
        <p>
And even though I hate the effort around writing books, I am seriously considering
to write a book about "Services" in the next months. There's a lot
of stuff here on the blog that should really be consolidated into a coherent story
and there are lots and lots of considerations and motiviations for decisons I
made for FABRIQ and Proseware and other services-related work that I should probably
write down in one place. One goal of the book would be to write a pragmatic guide
on how to design and build services using currently shipping (!) technologies
that does focus on how to get stuff done and not on how to craft new, exotic
SOAP headers, how to do WSDL trickery, or do other "cool" but not necessarily practical
things. So don't expect a 1200 page monster. 
</p>
        <p>
In addition to the "how to" part, I would also like to incorporate
and consolidate other architect's good (and bad) practical design and implementation
experiences, and write about adoption accelerators and barriers, and some other
aspects that are important to get the service idea past the CFO. That's a great
pain point for many people thinking about services today. If you would be interested
in contributing experiences (named or unnamed), I certainly would like <a href="mailto:clemensv@newtelligence.com&amp;subject=Book%20Project%20Architecture">to know</a> about
it.
</p>
        <p>
And I also think about a German-to-English translation and a significant
(English) update to my German-language <a href="http://www.amazon.de/exec/obidos/ASIN/3446221530/qid=1097925674/ref=sr_8_xs_ap_i1_xgl/302-5183842-4636033">Enterprise
Services</a> book.....
</p>
        <p>
[And to preempt the question: No, I don't have a publisher for either project, yet.]
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1fdd514d-cf1f-4350-a9b3-42cf8faa1740" />
      </body>
      <title>The to-do list and (maybe) a new book and (maybe) and new old book.</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,1fdd514d-cf1f-4350-a9b3-42cf8faa1740.aspx</guid>
      <link>http://vasters.com/clemensv/2004/10/16/The+Todo+List+And+Maybe+A+New+Book+And+Maybe+And+New+Old+Book.aspx</link>
      <pubDate>Sat, 16 Oct 2004 11:29:26 GMT</pubDate>
      <description>&lt;p&gt;
I feel like I have been "out of business" for a really long time and&amp;nbsp;like I really
got nothing done in the past 3 months, even though that's objectively not true. I
guess that's "conference &amp;amp; travel withdrawal", because I had tone and tons of
bigger events in the first half of the year and 3 smaller events since TechEd Amsterdam
in July.&amp;nbsp;On the upside, I am pretty relaxed&amp;nbsp;and have&amp;nbsp;certainly reduced
my stress-related health risks&amp;nbsp;;-)
&lt;/p&gt;
&lt;p&gt;
So with winter and its short days coming up, the other half of my life living a 1/3
around the planet until next spring, I can and am going to spend some serious time
on a bunch of things: 
&lt;/p&gt;
&lt;p&gt;
On the &lt;em&gt;new programming stuff&lt;/em&gt; front: 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Catch up on what has been going on in Indigo in recent months,
dig deeper into "everything Whidbey",&amp;nbsp;figure out the CLR aspects of&amp;nbsp;SQL
2005 and familiarize myself with VS Team System.
&lt;/p&gt;
&lt;p&gt;
On the &lt;em&gt;existing programming stuff&lt;/em&gt; front: 
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; Consolidate my "e:\development\*"&amp;nbsp; directory on my
harddrive and pull together all&amp;nbsp;my&amp;nbsp;samples and utilities for Enterprise
Services, ASP.NET Web Services and other enterprise-development technologies&amp;nbsp;and
create a production-quality&amp;nbsp;library from&amp;nbsp;of them for&amp;nbsp;us and our customers&amp;nbsp;to
use.&amp;nbsp;Also, because the Indigo team is doing quite a bit of COM/COM+ replumbing
recently in order to have that prohgraming model ride on Indigo,&amp;nbsp;I have some
hope that&amp;nbsp;I can now file bugs/wishes against COM+ that might have a chance of
being addressed. If that happens and&amp;nbsp;a particular&amp;nbsp;showstopper&amp;nbsp;is getting
out of the way, I will reopen this &lt;a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=110"&gt;project
here&lt;/a&gt; and will, at the very least, release it as a toy.
&lt;/p&gt;
&lt;p&gt;
On the &lt;em&gt;architectural stuff&lt;/em&gt; front:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Refine our SOA Workshop material,&amp;nbsp;do
quite a bit of additional work on the FABRIQ, evolve the Proseware architecture model,
and&amp;nbsp;get some pending projects done. In addition to our own SOA workshops (the
next English-language workshop is held &lt;a href="http://www.newtelligence.net/PermaLink.aspx?guid=245f5632-1ea1-4e0a-acd7-718cab67d3ab"&gt;December
1-3, 2004&amp;nbsp;in D&amp;#252;sseldorf&lt;/a&gt;), there will be a series of invite-only Microsoft
events on Service Orientation throughout Europe&amp;nbsp;this fall/winter, and I am very
happy that I will be speaking -- mostly on architecture topics -- at the Microsoft
Eastern Mediterranean Developer Conference in Amman/Jordan in November and several
other locations in the Middle East early next year.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
And even though I hate the effort around writing books, I&amp;nbsp;am&amp;nbsp;seriously considering
to write&amp;nbsp;a book&amp;nbsp;about "Services" in the next months.&amp;nbsp;There's a lot
of stuff here on the blog that should really be consolidated into a coherent story
and there are lots and lots of&amp;nbsp;considerations and motiviations for decisons I
made&amp;nbsp;for FABRIQ and Proseware and other services-related work that I should probably
write down in one place.&amp;nbsp;One goal of the book would be to&amp;nbsp;write a pragmatic&amp;nbsp;guide
on how to design and build services&amp;nbsp;using currently shipping&amp;nbsp;(!) technologies
that does focus on how to get stuff done and not&amp;nbsp;on how to craft new, exotic
SOAP headers, how to do WSDL trickery, or do other "cool" but not necessarily practical
things.&amp;nbsp;So don't expect a 1200 page monster.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
In addition&amp;nbsp;to the "how to" part,&amp;nbsp;I would also&amp;nbsp;like to&amp;nbsp;incorporate
and consolidate&amp;nbsp;other architect's good (and bad) practical design and implementation
experiences, and write about adoption accelerators and barriers,&amp;nbsp;and some other
aspects that are important to get the service idea past the CFO.&amp;nbsp;That's a great
pain point for many people thinking about services today. If you would be interested
in&amp;nbsp;contributing experiences (named or unnamed), I certainly would like &lt;a href="mailto:clemensv@newtelligence.com&amp;amp;subject=Book%20Project%20Architecture"&gt;to&amp;nbsp;know&lt;/a&gt; about
it.
&lt;/p&gt;
&lt;p&gt;
And I also think about&amp;nbsp;a German-to-English translation&amp;nbsp;and a significant
(English) update to my German-language&amp;nbsp;&lt;a href="http://www.amazon.de/exec/obidos/ASIN/3446221530/qid=1097925674/ref=sr_8_xs_ap_i1_xgl/302-5183842-4636033"&gt;Enterprise
Services&lt;/a&gt; book.....
&lt;/p&gt;
&lt;p&gt;
[And to preempt the question: No, I don't have a publisher for either project, yet.]
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1fdd514d-cf1f-4350-a9b3-42cf8faa1740" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,1fdd514d-cf1f-4350-a9b3-42cf8faa1740.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Blog</category>
      <category>IT Strategy</category>
      <category>newtelligence</category>
      <category>Other Stuff</category>
      <category>Talks</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=e04b46b3-64ee-442e-b24c-23947993db00</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,e04b46b3-64ee-442e-b24c-23947993db00.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,e04b46b3-64ee-442e-b24c-23947993db00.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=e04b46b3-64ee-442e-b24c-23947993db00</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <div class="Section1">
          <p>
A little while ago a new build of Indigo found its way onto my desk. On thing that’s
interesting about this particular interim milestone (don’t hope for juicy details
here on the blog) is that it doesn’t support WSDL. No. Calm down. It’s
not what you think. It just happens that the WSDL support wasn’t included in
this particular version; it’ll be there, no worries.
</p>
          <p>
Such interim binary drops that the Microsoft product groups give out to very early
adopters are really only meant for the bravest of the brave with too much time on
their hands. Therefore, the documentation is not entirely in synch with the feature
set – and that’s a stretch. (Hey, I am not complaining.) So until someone
told me “yeah, there’s no WSDL or Metadata exchange worth talking about
in this build” I tried to find how contract works in this build and of course
I couldn’t find it. Well, not really true. It turns out that contract works
just like with ASP.NET 1.0 or ASP.NET 1.1 Web Services. At runtime, WSDL usually doesn’t
play any role, at all. Unless you use some funky dynamic binding logic, WSDL is just
a design-time metadata container and that’s the basis for generating CLR metadata
and code. Although there is an implementation aspect to it when you generate proxies
or server skeletons, the most important job of WSDL.EXE is to perform a <i>conversion</i> of
the WSDL rendering of the message contract into a format that the ASMX infrastructure
can readily understand. That format happens to be classes with methods and attribute
annotations. Here is a client and a server I just typed up with Notepad:
</p>
          <table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" border="1">
            <tbody>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="347">
                  <p>
Contract.asmx
</p>
                </td>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="528">
                  <p>
Client.cs
</p>
                </td>
              </tr>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="347">
                  <p>
                    <span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'">&lt;% @WebService class="MyService"
language="C#"%&gt;<br /><br />
using System.Web.Services;<br />
using System.Web.Services.Protocols;<br /><br />
[WebService(Namespace="http://tempuri.org")]<br />
public class MyService<br />
{<br />
    [WebMethod]<br />
    public string Hello( string Test )<br />
    {<br />
       return "Hello "+Test;<br />
    }<br />
}</span>
                  </p>
                </td>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="528">
                  <p>
                    <span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'">using System;<br />
using System.Web.Services;<br />
using System.Web.Services.Protocols;<br /><br />
[WebServiceBinding(Namespace="http://tempuri.org")]<br />
public class MyService : SoapHttpClientProtocol<br />
{<br />
    [SoapDocumentMethod]<br />
    public string Hello( string Test )<br />
    {<br />
       return (string)Invoke("Hello", new object[]{Test})[0];<br />
    }<br />
}<br /><br />
public class MainApp<br />
{<br />
   static void Main()<br />
   {<br />
       MyService m = new MyService();<br />
       m.Url = "http://localhost/contract.asmx";<br />
       Console.WriteLine("Result: "+ m.Hello("Test"));<br />
   }<br />
}</span>
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          <p>
Drop the contract.asmx into x:\inetpub\wwwroot, compile the client with “csc
client.cs” and run it. No WSDL ever changed hands, no “Add Web Reference”,
it just works. Ok, ok, it’s the year ‘04 now and there’s really
no magic there anymore. Now here’s a tiny bit of refactoring: 
</p>
          <table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" border="1">
            <tbody>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="347">
                  <p>
Contract.asmx
</p>
                </td>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="528">
                  <p>
Client.cs
</p>
                </td>
              </tr>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="347">
                  <p>
                    <span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'">&lt;% @WebService class="MyService"
language="C#"%&gt;<br /><br />
using System.Web.Services;<br />
using System.Web.Services.Protocols;<br /><br /><br /><strong>public interface IMyService<br />
{<br />
    string Hello( string Test );<br />
}</strong><br /><br />
[WebService(Namespace="http://tempuri.org")]<br />
public class MyService : IMyService<br />
{<br />
    [WebMethod]<br />
    public string Hello( string Test )<br />
    {<br />
       return "Hello "+Test;<br />
    }<br />
}</span>
                  </p>
                </td>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="528">
                  <p>
                    <span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'">using System;<br />
using System.Web.Services;<br />
using System.Web.Services.Protocols;<br /><br /><br /><strong>public interface IMyService<br />
{<br />
    string Hello( string Test );<br />
}</strong><br /><br />
[WebServiceBinding(Namespace="http://tempuri.org")]<br />
public class MyService : SoapHttpClientProtocol, IMyService<br />
{<br />
    [SoapDocumentMethod]<br />
    public string Hello( string Test )<br />
    {<br />
       return (string)Invoke("Hello", new object[]{Test})[0];<br />
    }<br />
}<br /><br />
public class MainApp<br />
{<br />
   static void Main()<br />
   {<br />
       MyService m = new MyService();<br />
       m.Url = "http://localhost:8080/contract.asmx";<br />
       Console.WriteLine("Result: "+ m.Hello("Test"));<br />
   }<br />
}</span>
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          <p>
Extracting the interface from server and proxy makes it very, very clear that we’re
dealing with the very same message contract. Mind that we only have source-code level
contract equivalence between client and server here. The compiled code on either side
yields distinct IMyService types and that’s supposed to be that way. In the
case I am illustrating here, <i>the language C#</i> serves as the metadata language
(and the clipboard is the mechanism) for sharing contract between client and server
(or endpoints). 
</p>
          <p>
There are two things I find (mildly) annoying about ASP.Net Web Services 1.x and they
also become quite apparent in this example: #1 the server side and the client side
have a different minimum set of required attributes and #2 ASP.NET’s ASMX support
doesn’t look at inherited method-level attributes. The following <b>does not
even compile:</b></p>
          <table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" border="1">
            <tbody>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="347">
                  <p>
Contract.asmx
</p>
                </td>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="528">
                  <p>
Client.cs
</p>
                </td>
              </tr>
              <tr>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="347">
                  <p>
                    <span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'">&lt;% @WebService class="MyService"
language="C#"%&gt;<br /><br />
using System.Web.Services;<br />
using System.Web.Services.Protocols;<br /><br />
[WebServiceBinding(Namespace="http://tempuri.org")]<br />
[WebService(Namespace="http://tempuri.org")]<br />
public interface IMyService<br />
{<br />
    [SoapDocumentMethod][WebService]<br />
    string Hello( string Test );<br />
}<br /><br />
public class MyService : IMyService<br />
{<br />
    public string Hello( string Test )<br />
    {<br />
       return "Hello "+Test;<br />
    }<br />
}</span>
                  </p>
                </td>
                <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="528">
                  <p>
                    <span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'">using System;<br />
using System.Web.Services;<br />
using System.Web.Services.Protocols;<br /><br />
[WebServiceBinding(Namespace="http://tempuri.org")]<br />
[WebService(Namespace="http://tempuri.org")]<br />
public interface IMyService<br />
{<br />
    [SoapDocumentMethod][WebService]   <br />
    string Hello( string Test );<br />
}<br /><br />
public class MyService : SoapHttpClientProtocol, IMyService<br />
{<br />
    public string Hello( string Test )<br />
    {<br />
       return (string)Invoke("Hello", new object[]{Test})[0];<br />
    }<br />
}<br /><br />
public class MainApp<br />
{<br />
   static void Main()<br />
   {<br />
       MyService m = new MyService();<br />
       m.Url = "http://localhost:8080/contract.asmx";<br />
       Console.WriteLine("Result: "+ m.Hello("Test"));<br />
   }<br />
}</span>
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          <p>
And, frankly, it’s probably not bad that it doesn’t compile, because the
half of the attributes on the resulting interface declaration are useless on either
side. 
</p>
          <p>
Indigo pulls both sides together into the notion of a service contract that’s
good for either side (I am using a simple variant of the “publicly known”
notation here)
</p>
          <p>
            <span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'">[ServiceContract]<br />
public interface IMyService<br />
{<br />
    [ServiceMethod]<br />
    string Hello( string Test );<br />
}</span>
          </p>
          <p>
If you want to see it that way, this is <b>Indigo’s IDL </b>(Interface Definition
Language). There’s an equivalence transformation from and to WSDL, if you want
to share the contract with folks who program on other platforms or who use another
programming language. There are just no angle brackets here and it’s much easier
to read, too. 
</p>
          <p>
So if you see code that I wrote and you find (even today) seemingly unnecessary interface
declarations that are implemented on a single web service class within a project and
nowhere else and are also not referenced from anywhere – they might not be unnecessary
as they seem. It’s simply <b>IDL</b>! 
</p>
          <p>
More confusingly, you might find those declarations replicated! in source code! in
another service! Yes, because services are designed to be evolved independent of each
other. So while the target service is already in V4, the consumer may still be on
the level of V2. Moving up to the V4 interface version is a conscious choice by the
developer of the service consumer – and at that point in time he/she imports
the most recent contract. Whether that’s copy/paste of a C#/VB/C++ declaration
or clicking “Update” on some menu in Visual Studio that turns WSDL into
proxy code is not very important; it’s just a matter of tool preference.
</p>
          <p>
Using explicit interface declarations with Web Services is strictly a “contract
first” model. It’s just not using WSDL, that’s all.
</p>
        </div>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e04b46b3-64ee-442e-b24c-23947993db00" />
      </body>
      <title>Look, Ma! No WSDL! It's IDL!!</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,e04b46b3-64ee-442e-b24c-23947993db00.aspx</guid>
      <link>http://vasters.com/clemensv/2004/09/07/Look+Ma+No+WSDL+Its+IDL.aspx</link>
      <pubDate>Tue, 07 Sep 2004 11:09:18 GMT</pubDate>
      <description>&lt;div class=Section1&gt;
&lt;p&gt;
A little while ago a new build of Indigo found its way onto my desk. On thing that&amp;#8217;s
interesting about this particular interim milestone (don&amp;#8217;t hope for juicy details
here on the blog) is that it doesn&amp;#8217;t support WSDL. No. Calm down. It&amp;#8217;s
not what you think. It just happens that the WSDL support wasn&amp;#8217;t included in
this particular version; it&amp;#8217;ll be there, no worries.
&lt;/p&gt;
&lt;p&gt;
Such interim binary drops that the Microsoft product groups give out to very early
adopters are really only meant for the bravest of the brave with too much time on
their hands. Therefore, the documentation is not entirely in synch with the feature
set &amp;#8211; and that&amp;#8217;s a stretch. (Hey, I am not complaining.) So until someone
told me &amp;#8220;yeah, there&amp;#8217;s no WSDL or Metadata exchange worth talking about
in this build&amp;#8221; I tried to find how contract works in this build and of course
I couldn&amp;#8217;t find it. Well, not really true. It turns out that contract works
just like with ASP.NET 1.0 or ASP.NET 1.1 Web Services. At runtime, WSDL usually doesn&amp;#8217;t
play any role, at all. Unless you use some funky dynamic binding logic, WSDL is just
a design-time metadata container and that&amp;#8217;s the basis for generating CLR metadata
and code. Although there is an implementation aspect to it when you generate proxies
or server skeletons, the most important job of WSDL.EXE is to perform a &lt;i&gt;conversion&lt;/i&gt; of
the WSDL rendering of the message contract into a format that the ASMX infrastructure
can readily understand. That format happens to be classes with methods and attribute
annotations. Here is a client and a server I just typed up with Notepad:
&lt;/p&gt;
&lt;table class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing=0 cellpadding=0 border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=347&gt;
&lt;p&gt;
Contract.asmx
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=528&gt;
&lt;p&gt;
Client.cs
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=347&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;% @WebService class="MyService"
language="C#"%&amp;gt;&lt;br&gt;
&lt;br&gt;
using System.Web.Services;&lt;br&gt;
using System.Web.Services.Protocols;&lt;br&gt;
&lt;br&gt;
[WebService(Namespace="http://tempuri.org")]&lt;br&gt;
public class MyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [WebMethod]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Hello( string Test )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return "Hello "+Test;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=528&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'"&gt;using System;&lt;br&gt;
using System.Web.Services;&lt;br&gt;
using System.Web.Services.Protocols;&lt;br&gt;
&lt;br&gt;
[WebServiceBinding(Namespace="http://tempuri.org")]&lt;br&gt;
public class MyService : SoapHttpClientProtocol&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [SoapDocumentMethod]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Hello( string Test )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (string)Invoke("Hello", new object[]{Test})[0];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
public class MainApp&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; static void Main()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyService m = new MyService();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m.Url = "http://localhost/contract.asmx";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Result: "+ m.Hello("Test"));&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Drop the contract.asmx into x:\inetpub\wwwroot, compile the client with &amp;#8220;csc
client.cs&amp;#8221; and run it. No WSDL ever changed hands, no &amp;#8220;Add Web Reference&amp;#8221;,
it just works. Ok, ok, it&amp;#8217;s the year &amp;#8216;04 now and there&amp;#8217;s really
no magic there anymore. Now here&amp;#8217;s a tiny bit of refactoring: 
&lt;/p&gt;
&lt;table class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing=0 cellpadding=0 border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=347&gt;
&lt;p&gt;
Contract.asmx
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=528&gt;
&lt;p&gt;
Client.cs
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=347&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;% @WebService class="MyService"
language="C#"%&amp;gt;&lt;br&gt;
&lt;br&gt;
using System.Web.Services;&lt;br&gt;
using System.Web.Services.Protocols;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;public interface IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string Hello( string Test );&lt;br&gt;
}&lt;/strong&gt;
&lt;br&gt;
&lt;br&gt;
[WebService(Namespace="http://tempuri.org")]&lt;br&gt;
public class MyService : IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [WebMethod]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Hello( string Test )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return "Hello "+Test;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=528&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'"&gt;using System;&lt;br&gt;
using System.Web.Services;&lt;br&gt;
using System.Web.Services.Protocols;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;public interface IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string Hello( string Test );&lt;br&gt;
}&lt;/strong&gt;
&lt;br&gt;
&lt;br&gt;
[WebServiceBinding(Namespace="http://tempuri.org")]&lt;br&gt;
public class MyService : SoapHttpClientProtocol, IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [SoapDocumentMethod]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Hello( string Test )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (string)Invoke("Hello", new object[]{Test})[0];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
public class MainApp&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; static void Main()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyService m = new MyService();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m.Url = "http://localhost:8080/contract.asmx";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Result: "+ m.Hello("Test"));&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Extracting the interface from server and proxy makes it very, very clear that we&amp;#8217;re
dealing with the very same message contract. Mind that we only have source-code level
contract equivalence between client and server here. The compiled code on either side
yields distinct IMyService types and that&amp;#8217;s supposed to be that way. In the
case I am illustrating here, &lt;i&gt;the language C#&lt;/i&gt; serves as the metadata language
(and the clipboard is the mechanism) for sharing contract between client and server
(or endpoints). 
&lt;/p&gt;
&lt;p&gt;
There are two things I find (mildly) annoying about ASP.Net Web Services 1.x and they
also become quite apparent in this example: #1 the server side and the client side
have a different minimum set of required attributes and #2 ASP.NET&amp;#8217;s ASMX support
doesn&amp;#8217;t look at inherited method-level attributes. The following &lt;b&gt;does not
even compile:&lt;/b&gt;
&lt;/p&gt;
&lt;table class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing=0 cellpadding=0 border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=347&gt;
&lt;p&gt;
Contract.asmx
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=528&gt;
&lt;p&gt;
Client.cs
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 260.6pt; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=347&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;% @WebService class="MyService"
language="C#"%&amp;gt;&lt;br&gt;
&lt;br&gt;
using System.Web.Services;&lt;br&gt;
using System.Web.Services.Protocols;&lt;br&gt;
&lt;br&gt;
[WebServiceBinding(Namespace="http://tempuri.org")]&lt;br&gt;
[WebService(Namespace="http://tempuri.org")]&lt;br&gt;
public interface IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[SoapDocumentMethod][WebService]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string Hello( string Test );&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
public class MyService : IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Hello( string Test )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return "Hello "+Test;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: medium none; WIDTH: 5.5in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid" valign=top width=528&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'"&gt;using System;&lt;br&gt;
using System.Web.Services;&lt;br&gt;
using System.Web.Services.Protocols;&lt;br&gt;
&lt;br&gt;
[WebServiceBinding(Namespace="http://tempuri.org")]&lt;br&gt;
[WebService(Namespace="http://tempuri.org")]&lt;br&gt;
public interface IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [SoapDocumentMethod][WebService] &amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string Hello( string Test );&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
public class MyService : SoapHttpClientProtocol, IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Hello( string Test )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (string)Invoke("Hello", new object[]{Test})[0];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
public class MainApp&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; static void Main()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyService m = new MyService();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m.Url = "http://localhost:8080/contract.asmx";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Result: "+ m.Hello("Test"));&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
And, frankly, it&amp;#8217;s probably not bad that it doesn&amp;#8217;t compile, because the
half of the attributes on the resulting interface declaration are useless on either
side. 
&lt;/p&gt;
&lt;p&gt;
Indigo pulls both sides together into the notion of a service contract that&amp;#8217;s
good for either side (I am using a simple variant of the &amp;#8220;publicly known&amp;#8221;
notation here)
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'"&gt;[ServiceContract]&lt;br&gt;
public interface IMyService&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[ServiceMethod]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string Hello( string Test );&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
If you want to see it that way, this is &lt;b&gt;Indigo&amp;#8217;s IDL &lt;/b&gt;(Interface Definition
Language). There&amp;#8217;s an equivalence transformation from and to WSDL, if you want
to share the contract with folks who program on other platforms or who use another
programming language. There are just no angle brackets here and it&amp;#8217;s much easier
to read, too. 
&lt;/p&gt;
&lt;p&gt;
So if you see code that I wrote and you find (even today) seemingly unnecessary interface
declarations that are implemented on a single web service class within a project and
nowhere else and are also not referenced from anywhere &amp;#8211; they might not be unnecessary
as they seem. It&amp;#8217;s simply &lt;b&gt;IDL&lt;/b&gt;! 
&lt;/p&gt;
&lt;p&gt;
More confusingly, you might find those declarations replicated! in source code! in
another service! Yes, because services are designed to be evolved independent of each
other. So while the target service is already in V4, the consumer may still be on
the level of V2. Moving up to the V4 interface version is a conscious choice by the
developer of the service consumer &amp;#8211; and at that point in time he/she imports
the most recent contract. Whether that&amp;#8217;s copy/paste of a C#/VB/C++ declaration
or clicking &amp;#8220;Update&amp;#8221; on some menu in Visual Studio that turns WSDL into
proxy code is not very important; it&amp;#8217;s just a matter of tool preference.
&lt;/p&gt;
&lt;p&gt;
Using explicit interface declarations with Web Services is strictly a &amp;#8220;contract
first&amp;#8221; model. It&amp;#8217;s just not using WSDL, that&amp;#8217;s all.
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e04b46b3-64ee-442e-b24c-23947993db00" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,e04b46b3-64ee-442e-b24c-23947993db00.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=0339fe35-2328-44be-93e6-f004bd869a84</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,0339fe35-2328-44be-93e6-f004bd869a84.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,0339fe35-2328-44be-93e6-f004bd869a84.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=0339fe35-2328-44be-93e6-f004bd869a84</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
(1) <strong>P</strong>olicy-negotiated behavior, (2) <strong>E</strong>xplicitness
of Boundaries, (3) <strong>A</strong>utonomy and (4) <strong>C</strong>ontract/Schema <strong>E</strong>xchange
are the proclaimed tenets of service orientation. As I am getting along with the design
for the services infrastructure we're working on, I find that one of the four towers
the others in importance and really doesn't really fit well with them: Autonomy.
</p>
        <p>
          <strong>P</strong>, <strong>E</strong> and <strong>CE</strong> say things about
the edge of a service. <strong>P</strong> speaks about how a service negotiates its
edge behavior, guarantees and expectations with others. <strong>E</strong> speaks
about how talking to another service is and must be different from talking to anything
within your own service. <strong>CE</strong> speaks about how it is possible to establish
a common understanding about messages and data while allowing independent evolution
of internals by not sharing programming-level type constructs. 
</p>
        <p>
          <strong>P </strong>is about creating and using techniques for metadata exchange
and metadata controlled dynamic configuration of service-edges, <strong>E </strong>is
about creating and using techniques for shaping service-edge communication paths and
tools in a way that services don't get into each others underwear, and <strong>CE </strong>is
about techniques for defining, exchanging, and implementing the flow of data across
service-edges so that services can deal with each other's "stuff".
</p>
        <p>
P, E and CE are guiding tenets for "Web Services" and the stack that evolves
around SOAP. These are about "edge stuff". Proper tooling around SOAP, WSDL, XML Schema,
WS-Policy (think ASMX, WSE, Axis, or Indigo) makes or will make it relatively
easy for any programmer to do "the right thing" about these tenets.
</p>
        <p>
          <strong>A</strong>utonomy, on the other hand, is rather independent from the
edge of a service. It describes a fundamental approach to architecture. An "autonomous digital
entity" is "alive", makes independent decisions, hides its internals, and is
in full control of the data it owns. An autonomous digital entity is not fully
dependent on stuff happening on its edge or on inbound commands or requests. Instead,
an autonomous service may routinely wake up from a self-chosen cryostasis and
check whether certain data items that it is taking care of are
becoming due for some actions, or it may decide that it is time to switch
on the lights and lower the windows blinds to fends off burglars while its owner
is on vacation. 
</p>
        <p>
          <strong>A</strong>utonomy is actually quite difficult to (teach and) achieve
and much more a matter of discipline than a matter of tooling. If you have two
"Web services" that sit on top of the very same data store and frequently touch what's
supposed to be each others private (data) parts, each of them may very well fulfill
the P, E, CE tenets, but they are not autonomous. If you try to scale out
and host such a pair or group of Web services in separate locations and on top of
separate stores, you end up with a very complicated Siamese-twins-separation
surgery.  
</p>
        <p>
That gets me to very clearly separate the two stories: Web Services &lt;&gt;
Services.
</p>
        <p>
A <strong>service</strong> is an autonomous digital entity that may or may not accept
commands, inquiries (and data) from the outside world. If it chooses
to accept such input, it can choose to do so through one or more <strong>web
service</strong> edges that fulfill the P,E,CE tenets and/or may choose
to accept totally different forms of input. If it communicates with the outside world
from within, it may or may choose to do so via <strong>web services</strong>. <u>A
service is a program.</u></p>
        <p>
A <strong>web service</strong> is an implementation of a set of edge definitions
(policies and contracts and channels) that <em>fronts</em> a <strong>service</strong> and
allows <strong>services</strong> to communicate with each other. Two <strong>services</strong> may
choose to communicate using multiple <strong>web services</strong>, if they wish to
do so. <u>A web service is a communication tool.</u></p>
        <p>
With that, I'll cite myself from three paragraphs earlier: <em>If you have two "Web
services" that sit on top of the very same data store [...] they are not autonomous.
If you try to scale out [...] you end up with a very complicated Siamese-twins-separation
surgery."  </em>... and correct myself: If you have two "<strong>Web services</strong>",
they don't sit on the data store, they front a <strong>service</strong>. The <strong>service</strong> is
the smallest deployable unit. The <strong>service</strong> provides the A, the <strong>web
services</strong> bring P, E and CE to the table. A <strong>web service</strong> may,
indeed, just be a message router, security gateway, translator or other intermediary
that handles messages strictly on the wire-level and dispatches them to yet another <strong>web
service</strong> fronting an actual <strong>service </strong>that does the work prescribed
by the message. 
</p>
        <p>
All of this, of course, causes substantial confusion about the duplicate
use of the word <em>service</em>. The above it terribly difficult to read. I would wish
it was still possible to kill the (inapproprate) term "web service" and
just call it "edge", or "XML Edge", or (for the marketing people) "SOAP Edge Technology", or
maybe "Service Edge XML", although I don't think the resulting acronym would go over
well in the U.S.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=0339fe35-2328-44be-93e6-f004bd869a84" />
      </body>
      <title>"The PEACE service orientation tenets are not 4, they are 3+1" OR "Services vs.Web Services"</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,0339fe35-2328-44be-93e6-f004bd869a84.aspx</guid>
      <link>http://vasters.com/clemensv/2004/08/18/The+PEACE+Service+Orientation+Tenets+Are+Not+4+They+Are+31+OR+Services+VsWeb+Services.aspx</link>
      <pubDate>Wed, 18 Aug 2004 11:51:20 GMT</pubDate>
      <description>&lt;p&gt;
(1) &lt;strong&gt;P&lt;/strong&gt;olicy-negotiated behavior, (2)&amp;nbsp;&lt;strong&gt;E&lt;/strong&gt;xplicitness
of Boundaries, (3)&amp;nbsp;&lt;strong&gt;A&lt;/strong&gt;utonomy and (4)&amp;nbsp;&lt;strong&gt;C&lt;/strong&gt;ontract/Schema &lt;strong&gt;E&lt;/strong&gt;xchange
are the proclaimed tenets of service orientation. As I am getting along with the design
for the services infrastructure we're working on, I find that one of the four towers
the others in importance and&amp;nbsp;really doesn't really fit well with them: Autonomy.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;P&lt;/strong&gt;, &lt;strong&gt;E&lt;/strong&gt; and &lt;strong&gt;CE&lt;/strong&gt; say&amp;nbsp;things about
the edge of a service. &lt;strong&gt;P&lt;/strong&gt; speaks about how a service negotiates its
edge behavior, guarantees and expectations with others. &lt;strong&gt;E&lt;/strong&gt; speaks
about how talking to another service is and must be different from talking to anything
within your own service. &lt;strong&gt;CE&lt;/strong&gt; speaks about how it is possible to establish
a common understanding about messages and data while allowing independent evolution
of internals by not sharing programming-level type constructs. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;P &lt;/strong&gt;is about creating and using techniques&amp;nbsp;for metadata exchange
and metadata controlled dynamic configuration of service-edges, &lt;strong&gt;E &lt;/strong&gt;is
about creating and using techniques for shaping service-edge communication paths and
tools in a way that services don't get into each others underwear, and &lt;strong&gt;CE &lt;/strong&gt;is
about techniques for defining, exchanging, and implementing the flow of data across
service-edges so that services can deal with each other's "stuff".
&lt;/p&gt;
&lt;p&gt;
P, E and CE are&amp;nbsp;guiding&amp;nbsp;tenets for "Web Services" and the stack that evolves
around SOAP. These are about "edge stuff". Proper tooling around SOAP, WSDL, XML Schema,
WS-Policy (think ASMX, WSE, Axis,&amp;nbsp;or Indigo) makes or will make it relatively
easy for any programmer to do "the right thing" about these tenets.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;A&lt;/strong&gt;utonomy, on the other hand,&amp;nbsp;is rather independent from&amp;nbsp;the
edge of a service. It describes&amp;nbsp;a fundamental approach to architecture. An "autonomous&amp;nbsp;digital
entity"&amp;nbsp;is "alive", makes independent decisions, hides its internals, and is
in full control of the data it owns. An autonomous&amp;nbsp;digital entity&amp;nbsp;is not&amp;nbsp;fully
dependent on&amp;nbsp;stuff happening on its edge or on inbound&amp;nbsp;commands or requests.&amp;nbsp;Instead,
an autonomous&amp;nbsp;service may routinely wake up from a self-chosen cryostasis and
check&amp;nbsp;whether&amp;nbsp;certain data items that it&amp;nbsp;is&amp;nbsp;taking care of&amp;nbsp;are
becoming due for some actions,&amp;nbsp;or it may&amp;nbsp;decide that it is time to switch
on the lights and lower the windows blinds to fends off burglars while&amp;nbsp;its owner
is on vacation.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;A&lt;/strong&gt;utonomy is actually quite&amp;nbsp;difficult to (teach and) achieve
and much more a matter of discipline than a matter of tooling.&amp;nbsp;If you have two
"Web services" that sit on top of the very same data store and frequently touch what's
supposed to be each others private (data) parts, each of them may very well fulfill
the&amp;nbsp;P, E, CE&amp;nbsp;tenets, but they are not autonomous. If you try to scale out
and host such a pair or group of Web services in separate locations and on top of
separate stores, you end up with a&amp;nbsp;very complicated&amp;nbsp;Siamese-twins-separation
surgery.&amp;nbsp;&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
That gets me to&amp;nbsp;very clearly separate&amp;nbsp;the two stories: Web Services &amp;lt;&amp;gt;
Services.
&lt;/p&gt;
&lt;p&gt;
A &lt;strong&gt;service&lt;/strong&gt; is an autonomous digital entity that may or may not&amp;nbsp;accept
commands, inquiries&amp;nbsp;(and data)&amp;nbsp;from the outside world. If it&amp;nbsp;chooses
to accept such input, it can choose to do so through&amp;nbsp;one or more&amp;nbsp;&lt;strong&gt;web
service&lt;/strong&gt;&amp;nbsp;edges that fulfill the P,E,CE tenets&amp;nbsp;and/or may choose
to accept totally different forms of input. If it communicates with the outside world
from within, it may or may choose to do so via &lt;strong&gt;web services&lt;/strong&gt;. &lt;u&gt;A
service is a program.&lt;/u&gt;
&lt;/p&gt;
&lt;p&gt;
A &lt;strong&gt;web service&lt;/strong&gt; is&amp;nbsp;an implementation of a set of&amp;nbsp;edge definitions
(policies and contracts and channels) that &lt;em&gt;fronts&lt;/em&gt; a &lt;strong&gt;service&lt;/strong&gt; and
allows &lt;strong&gt;services&lt;/strong&gt; to communicate with each other. Two &lt;strong&gt;services&lt;/strong&gt; may
choose to communicate using multiple &lt;strong&gt;web services&lt;/strong&gt;, if they wish to
do so. &lt;u&gt;A web service is a communication tool.&lt;/u&gt;
&lt;/p&gt;
&lt;p&gt;
With that, I'll cite myself from three paragraphs earlier: &lt;em&gt;If you have two "Web
services" that sit on top of the very same data store [...] they are not autonomous.
If you try to scale out [...] you end up with a&amp;nbsp;very complicated&amp;nbsp;Siamese-twins-separation
surgery."&amp;nbsp; &lt;/em&gt;... and correct myself: If you have two "&lt;strong&gt;Web services&lt;/strong&gt;",
they don't sit on the data store, they&amp;nbsp;front a &lt;strong&gt;service&lt;/strong&gt;. The &lt;strong&gt;service&lt;/strong&gt; is
the smallest deployable unit. The &lt;strong&gt;service&lt;/strong&gt; provides the A, the &lt;strong&gt;web
services&lt;/strong&gt; bring P, E and CE to the table.&amp;nbsp;A &lt;strong&gt;web service&lt;/strong&gt; may,
indeed, just be a message router, security gateway, translator&amp;nbsp;or other intermediary
that handles messages strictly on the wire-level and dispatches them to yet another &lt;strong&gt;web
service&lt;/strong&gt; fronting an actual &lt;strong&gt;service &lt;/strong&gt;that does the work&amp;nbsp;prescribed
by the message.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
All of this, of course,&amp;nbsp;causes&amp;nbsp;substantial&amp;nbsp;confusion about the duplicate
use of the word &lt;em&gt;service&lt;/em&gt;. The above it terribly difficult to read. I would&amp;nbsp;wish
it was still&amp;nbsp;possible to kill&amp;nbsp;the (inapproprate) term "web service" and
just call it "edge", or "XML Edge", or (for the marketing people) "SOAP Edge Technology",&amp;nbsp;or
maybe "Service Edge XML", although I don't think the resulting acronym would go over
well in the U.S.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=0339fe35-2328-44be-93e6-f004bd869a84" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,0339fe35-2328-44be-93e6-f004bd869a84.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=9f7f99f4-8786-43c7-8944-2f94fba972f0</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,9f7f99f4-8786-43c7-8944-2f94fba972f0.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,9f7f99f4-8786-43c7-8944-2f94fba972f0.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=9f7f99f4-8786-43c7-8944-2f94fba972f0</wfw:commentRss>
      <slash:comments>9</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I don't blog much in summer. That's mostly because I am either enjoying some time
off or I am busy figuring out "new stuff". 
</p>
        <p>
So here's a bit of a hint what currently keeps me busy. If you read this in an RSS
aggregator, you better come to the <a href="http://staff.newtelligence.net/clemensv">website</a> for
this explanation to make sense. 
</p>
        <p>
This page here is composed from several elements. There are navigation elements on
the left, including a calendar, a categories tree and an archive link list that
are built based on index information of the content store. The rest of the page, header
and footer elements aside, contains the articles, which are composed onto the page
based on a set of rules and there's some content aggregation going on to produce,
for instance, the comment counter. Each of these jobs takes a little time and they
are worked on sequentially, while the data is acquired from the backend, the web-site
(rendering) thread sits idle.
</p>
        <p>
Likewise, imagine you have an intranet web portal that's customizable and gives the
user all sorts of individual information like the items on his/her task
list, the unread mails, today's weather at his/her location, a list of current projects
and their status, etc.  All of these are little visual components on the
page that are individually requested and each data item takes some time (even
if not much) to acquire. Likely more than here on this dasBlog site. And all the information
comes from several, distributed services with the portal page providing the visual
aggregation. Again, usually all these things are worked on sequentially. If you have
a dozen of those elements on a page and it takes unusually long to get one of them,
you'll still sit there and wait for the whole dozen. If the browser times out on you
during the wait, you won't get anything, even if 11 out of 12 information items could
be acquired. 
</p>
        <p>
One aspect of what I am working having all those 12 things done at
the same time and allow the rendering thread to do a little bit of work whenever one
of the items is ready and to allow the page to proceed whenever it loses its patience
with one or more of those jobs. So all of the data acquisition work happens in parallel
rather than in sequence and the results can be collected and processed in random order
and as they are ready. What's really exciting about this from an SOA perspective is
that I am killing request/response in the process. The model sits entirely on one-way
messaging. No return values, not output parameters anywhere in sight. 
</p>
        <p>
In case you wondered why it is so silent around here ... that's why. 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=9f7f99f4-8786-43c7-8944-2f94fba972f0" />
      </body>
      <title>The silence of summer</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,9f7f99f4-8786-43c7-8944-2f94fba972f0.aspx</guid>
      <link>http://vasters.com/clemensv/2004/08/06/The+Silence+Of+Summer.aspx</link>
      <pubDate>Fri, 06 Aug 2004 14:40:44 GMT</pubDate>
      <description>&lt;p&gt;
I don't blog much in summer. That's mostly because I am either enjoying some time
off or I am busy figuring out "new stuff". 
&lt;/p&gt;
&lt;p&gt;
So here's a bit of a hint what currently keeps me busy. If you read this in an RSS
aggregator, you better come to the &lt;a href="http://staff.newtelligence.net/clemensv"&gt;website&lt;/a&gt; for
this explanation to make sense. 
&lt;/p&gt;
&lt;p&gt;
This page here is composed from several elements. There are navigation elements on
the left, including a calendar, a categories tree&amp;nbsp;and an archive link list that
are built based on index information of the content store. The rest of the page, header
and footer elements aside, contains the articles, which are composed onto the page
based on a set of rules and there's some content aggregation going on to produce,
for instance, the comment counter. Each of these jobs takes a little time and they
are worked on sequentially, while the data is acquired from the backend, the web-site
(rendering) thread sits idle.
&lt;/p&gt;
&lt;p&gt;
Likewise, imagine you have an intranet&amp;nbsp;web portal that's customizable and gives&amp;nbsp;the
user&amp;nbsp;all sorts of&amp;nbsp;individual information like the items on his/her task
list, the unread mails, today's weather at his/her location, a list of current projects
and their status, etc.&amp;nbsp; All of these are little visual components&amp;nbsp;on the
page that are individually requested and&amp;nbsp;each data item takes some time (even
if not much) to acquire. Likely more than here on this dasBlog site. And all the information
comes from several, distributed services with the portal page providing the visual
aggregation. Again, usually all these things are worked on sequentially. If you have
a dozen of those elements on a page and it takes unusually long to get one of them,
you'll still sit there and wait for the whole dozen. If the browser times out on you
during the wait, you won't get anything, even if 11 out of 12 information items could
be acquired. 
&lt;/p&gt;
&lt;p&gt;
One aspect of what&amp;nbsp;I am working&amp;nbsp;having&amp;nbsp;all those 12 things done at
the same time and allow the rendering thread to do a little bit of work whenever one
of the items is ready and to allow the page to proceed whenever it loses its patience
with one or more of those jobs. So all of the data acquisition work happens in parallel
rather than in sequence and the results can be collected and processed in random order
and as they are ready. What's really exciting about this from an SOA perspective is
that I am killing request/response in the process. The model sits entirely on one-way
messaging.&amp;nbsp;No return values, not output parameters anywhere in sight. 
&lt;/p&gt;
&lt;p&gt;
In case you wondered why it is so silent around here ... that's why. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=9f7f99f4-8786-43c7-8944-2f94fba972f0" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,9f7f99f4-8786-43c7-8944-2f94fba972f0.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=514bac78-5c4e-4c57-9c15-e7736c83aa1d</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=514bac78-5c4e-4c57-9c15-e7736c83aa1d</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I was a little off when I compared <a href="http://staff.newtelligence.net/clemensv/CommentView.aspx?guid=1214e26d-674e-4a5c-b716-eaa07d327705">my
problem here</a> to a tail call. <a href="http://www.eighty-twenty.net/blog/urn:www-eighty-twenty-net:1250.html">Gordon
Weakliem</a> corrected me with the term "continuation".
</p>
        <p>
The fact that the post got 28 comments shows that this seems to be an interesting
problem and, naming aside, it is indeed a tricky thing to implement in a
framework when the programming language you use (C# in my case) doesn't support the
construct. What's specifically tricky about the concrete case that I have
is that I don't know where I am yielding control to at the time when I make the
respective call. 
</p>
        <p>
I'll recap. Assume there is the following call
</p>
        <p>
          <font size="4">
            <font face="Courier New">
              <font size="2">CustomerService cs = <font color="#0000ff">new</font></font>
            </font>
            <font face="Courier New" size="2"> CustomerService();<br /></font>
            <font size="2">
              <font face="Courier New">cs.FindCustomer(customerId);</font>
            </font>
          </font>
        </p>
        <p>
          <em>FindCustomer </em>is a call that will not return any result as a return value.
Instead, the invoked service comes back into the caller's program at some
completely different place such this:
</p>
        <p>
          <font size="4">
            <font face="Courier New">
              <font size="2">[WebMethod]<br />
public<font color="#000000"></font><font color="#0000ff">void</font></font>
            </font>
            <font face="Courier New">
              <font size="2">
                <font color="#000000"> FindCustomerReply(Customer[]
result)<br /></font>{<br />
   ...<br /></font>
            </font>
            <font size="2">
              <font face="Courier New">}</font>
            </font>
          </font>
        </p>
        <p>
So what we have here is a "duplex" conversation. The result of an operation initiated
by an outbound message (call) is received, some time later, through an inbound
message (call), but not on the same thread and not on the same "object". You
could say that this is a callback, but that's not precisely what it is, because a
"callback" usually happens while the initiating call (as above <em>FindCustomer</em>)
has not yet returned back to its scope or at least while the initiating object (or
an object passed by some sort of reference) is still alive. Here, instead, processing
of the <em>FindCustomer</em> call may take a while and the initiating thread and the
initiating object may be long gone when the answer is ready.
</p>
        <p>
Now, the additional issue I have is that at the time when the <em>FindCustomer</em> call
is made, it is not known what "<em>FindCustomerReply</em>" message handler it
going to be processing the result and it is really not know what's happening next.
The decision about what happens next and which handler is chosen is dependent on several
factors, including the time that it takes to receive the result. If the <em>FindCustomer</em> is
called from a web-page and the service providing <em>FindCustomer</em> drops
a result at the caller's doorstep within 2-3 seconds [1], the <em>FindCustomerReply</em> handler can
go and hijack the initial call's thread (and HTTP context) and render a page
showing the result. If the reply takes longer, the web-page (the caller) may lose
its patience [2] and choose to continue by rendering a page that says "We are sending
the result to your email account." and the message handler with not throw HTML into
an HTTP response on an open socket, but rather render it to an email and send
it via SMTP and maybe even alert the user through his/her Instant Messenger when/if
the result arrives.
</p>
        <p>
          <font size="4">
            <font face="Courier New">
              <font size="2">[1] HTTP Request =&gt; </font>
            </font>
            <font size="2">
              <font face="Courier New">FindCustomer()
=?&gt; "<font color="#000000">FindCustomerReply" =&gt; yield to CustomerList.aspx
=&gt; HTTP Response<br /><font color="#003300">[2] HTTP Request =&gt; </font><font size="2"><font face="Courier New"><font color="#003300">FindCustomer()
=?&gt; </font><font color="#000000">Timeout!           
=&gt; yield to YouWillGetMail.aspx =&gt; HTTP Response<br />
                               T+n =?&gt;
"FindCustomerReply" =&gt; SMTP Mail<br />
                                                          
=&gt; IM Notification</font></font></font></font></font>
            </font>
          </font>
        </p>
        <p>
So, in case [1] I need to correlate the reply with the request and continue processing
on the original thread. In case [2], the original thread continues on a
"default path" without an available reply and the reply is processed on (possibly
two) independent threads and using two different notification channels.
</p>
        <p>
A slightly different angle. Consider a workflow application environment in a bank,
where users are assigned tasks and simply fetch the next thing from the to-do
list (by clicking a link in an HTML-rendered list). The reply that results from "<em>LookupAndDoNextTask</em>" is
a message that contains the job that the user is supposed to do.  
</p>
        <p>
          <font face="Courier New">[1] HTTP Request =&gt; LookupAndDoNextTask<font size="2">()
=?&gt; Job: "<font color="#000000">Call Customer" =&gt; yield to CallCustomer.aspx =&gt;
HTTP Response<br /></font></font></font>
          <font face="Courier New">[2] HTTP Request =&gt; LookupAndDoNextTask<font size="2">()
=?&gt; Job: "<font color="#000000">Review Credit Offer" =&gt; yield to ReviewCredit.aspx =&gt;
HTTP Response<br /><font color="#003300">[3] HTTP Request =&gt; LookupAndDoNextTask</font><font size="2"><font color="#003300">()
=?&gt; Job: "</font><font color="#000000">Approve Mortgage" =&gt; yield to ApproveMortgage.aspx =&gt;
HTTP Response<br /><font color="#003300">[4] HTTP Request =&gt; LookupAndDoNextTask</font><font size="2"><font color="#003300">()
=?&gt; No Job / Timeout</font><font color="#000000"> =&gt; yield to Solitaire.aspx =&gt;
HTTP Response</font></font></font></font></font></font></font>
        </p>
        <p>
In all of these cases, calls to "FindCustomer()" and "LookupAndDoTask()" that are
made from the code that deals with the incoming request will (at least in the theoretical
model) never return to their caller and the thread will continue to execute in a different
context that is "TBD" at the time of the call. By the time the call stack is
unwound and the initiating call (like FindCustomer) indeed returns, the request
is therefore fully processed and the caller may not perform any further
actions. 
</p>
        <p>
So the issue at hand is to make that fact clear in the programming model. In ASP.NET,
there is a single construct called "Server.Transfer()" for that sort of continuation,
but it's very specific to ASP.NET and requires that the caller knows where you want
to yield control to. In the case I have here, the caller knows that it is surrendering
the thread to some other handler, but it doesn't know to to whom, because this is
dynamically determined by the underlying frameworks. All that's visible and should
be visible in the code is a "normal" method call.
</p>
        <p>
          <font size="4">
            <font size="2">
              <font face="Courier New">cs.FindCustomer(customerId) </font>
              <font face="Verdana">might
therefore not be a good name, because it looks "too normal". And of course I
don't have the powers to invent a new statement for the C# language
like </font>
              <font face="Courier New">
                <strong>continue(</strong>cs.FindCustomer(customerId)<strong>)</strong></font>
              <font face="Verdana"> that
would result in a continuation that simply doesn't return to the call location. Since
I can't do that, there has to be a different way to flag it. Sure, I could put an
attribute on the method, but Intellisense wouldn't show that, would it? So it seems
the best way is to have a convention of prefixing the method name.</font>
            </font>
          </font>
        </p>
        <p>
There were a bunch of ideas in the comments for method-name prefixes. Here is a selection: 
</p>
        <ul>
          <li>
            <font face="Courier New">cs.InitiateFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.YieldFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.YieldToFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.InjectFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.PlaceRequestFindCustomer(customerId)</font>
          </li>
          <li>
            <font face="Courier New">cs.PostRequestFindCustomer(customerId)</font>
          </li>
        </ul>
        <p>
I've got most of the underlying correlation and dispatch infrastructure
sitting here, but finding a good programming model for that sort of behavior
is quite difficult. 
</p>
        <p>
          <em>[Of course, this post won't make it on Microsoft Watch, eWeek or The
Register]</em>
        </p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=514bac78-5c4e-4c57-9c15-e7736c83aa1d" />
      </body>
      <title>Naming and Continuations (continued)</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/21/Naming+And+Continuations+Continued.aspx</link>
      <pubDate>Wed, 21 Jul 2004 08:24:16 GMT</pubDate>
      <description>&lt;p&gt;
I&amp;nbsp;was a little off&amp;nbsp;when I&amp;nbsp;compared&amp;nbsp;&lt;a href="http://staff.newtelligence.net/clemensv/CommentView.aspx?guid=1214e26d-674e-4a5c-b716-eaa07d327705"&gt;my
problem here&lt;/a&gt; to a tail call. &lt;a href="http://www.eighty-twenty.net/blog/urn:www-eighty-twenty-net:1250.html"&gt;Gordon
Weakliem&lt;/a&gt; corrected me with the term "continuation".
&lt;/p&gt;
&lt;p&gt;
The fact that the post got 28 comments shows that this seems to be an interesting
problem and, naming aside, it&amp;nbsp;is indeed a tricky thing to&amp;nbsp;implement in a
framework when the programming language you use (C# in my case) doesn't support the
construct.&amp;nbsp;What's specifically tricky about the&amp;nbsp;concrete case that I have
is that I don't&amp;nbsp;know where I am yielding control to at the time when I make the
respective call. 
&lt;/p&gt;
&lt;p&gt;
I'll recap. Assume there is the following call
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;CustomerService&amp;nbsp;cs = &lt;font color=#0000ff&gt;new&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt; CustomerService();&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;cs.FindCustomer(customerId);&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;FindCustomer &lt;/em&gt;is a&amp;nbsp;call that will not return any result as a return value.
Instead,&amp;nbsp;the invoked service&amp;nbsp;comes back into the caller's program at some
completely different place such this:
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;[WebMethod]&lt;br&gt;
public&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt; FindCustomerReply(Customer[]
result)&lt;br&gt;
&lt;/font&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp; ...&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
So what we have here is a "duplex" conversation. The result of an operation initiated
by an outbound&amp;nbsp;message (call) is received, some time later,&amp;nbsp;through an inbound
message&amp;nbsp;(call), but not on the same thread and not on the same "object".&amp;nbsp;You
could say that this is a callback, but that's not precisely what it is, because&amp;nbsp;a
"callback" usually happens&amp;nbsp;while the&amp;nbsp;initiating call (as above &lt;em&gt;FindCustomer&lt;/em&gt;)
has not yet returned back to its scope or at least while the initiating object (or
an object passed by some sort of reference) is still alive.&amp;nbsp;Here, instead,&amp;nbsp;processing
of the &lt;em&gt;FindCustomer&lt;/em&gt; call may take a while and the initiating thread and the
initiating object may be long gone when the answer is ready.
&lt;/p&gt;
&lt;p&gt;
Now, the additional issue I have is that at the time when the &lt;em&gt;FindCustomer&lt;/em&gt; call
is made, it is not&amp;nbsp;known what "&lt;em&gt;FindCustomerReply&lt;/em&gt;" message handler it
going to be processing the result and it is really not know what's happening next.
The decision about what happens next and which handler is chosen is dependent on several
factors, including the time that it takes to receive the result. If the &lt;em&gt;FindCustomer&lt;/em&gt; is
called from a web-page and the service providing &lt;em&gt;FindCustomer&lt;/em&gt;&amp;nbsp;drops
a result at the caller's doorstep within 2-3 seconds [1], the &lt;em&gt;FindCustomerReply&lt;/em&gt; handler&amp;nbsp;can
go and&amp;nbsp;hijack the initial call's thread (and HTTP context) and render a page
showing the result. If the reply takes longer, the web-page (the caller) may lose
its patience [2] and choose to continue by rendering a page that says "We are sending
the result to your email account." and the message handler with not throw HTML into
an&amp;nbsp;HTTP response on an open socket, but rather render it to an email and send
it via SMTP and maybe even alert the user through his/her Instant Messenger&amp;nbsp;when/if
the result arrives.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;[1] HTTP Request =&amp;gt; &lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;FindCustomer()
=?&amp;gt; "&lt;font color=#000000&gt;FindCustomerReply" =&amp;gt; yield to CustomerList.aspx =&amp;gt;
HTTP Response&lt;br&gt;
&lt;font color=#003300&gt;[2] HTTP Request =&amp;gt; &lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;&lt;font color=#003300&gt;FindCustomer()
=?&amp;gt; &lt;/font&gt;&lt;font color=#000000&gt;Timeout!&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
=&amp;gt; yield to YouWillGetMail.aspx =&amp;gt; HTTP Response&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T+n&amp;nbsp;=?&amp;gt;
"FindCustomerReply" =&amp;gt; SMTP Mail&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
=&amp;gt; IM Notification&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
So, in case [1] I need to correlate the reply with the request and&amp;nbsp;continue processing
on the original thread. In&amp;nbsp;case [2], the original thread continues&amp;nbsp;on&amp;nbsp;a
"default path"&amp;nbsp;without an available reply and the reply is processed on (possibly
two) independent threads and using two different notification channels.
&lt;/p&gt;
&lt;p&gt;
A slightly different angle. Consider a workflow application environment in a bank,
where users are assigned tasks and simply fetch the next thing&amp;nbsp;from the to-do
list (by clicking a link in an HTML-rendered list). The reply that results from "&lt;em&gt;LookupAndDoNextTask&lt;/em&gt;"&amp;nbsp;is
a message that contains the job that the user is supposed to do. &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;[1] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;font size=2&gt;()
=?&amp;gt; Job: "&lt;font color=#000000&gt;Call Customer" =&amp;gt; yield to CallCustomer.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;[2] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;font size=2&gt;()
=?&amp;gt; Job: "&lt;font color=#000000&gt;Review Credit Offer" =&amp;gt; yield to ReviewCredit.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;br&gt;
&lt;font color=#003300&gt;[3] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#003300&gt;()
=?&amp;gt; Job: "&lt;/font&gt;&lt;font color=#000000&gt;Approve Mortgage" =&amp;gt; yield to ApproveMortgage.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;br&gt;
&lt;font color=#003300&gt;[4] HTTP Request =&amp;gt; LookupAndDoNextTask&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#003300&gt;()
=?&amp;gt;&amp;nbsp;No Job / Timeout&lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;=&amp;gt; yield to Solitaire.aspx&amp;nbsp;=&amp;gt;
HTTP Response&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
In all of these cases, calls to "FindCustomer()" and "LookupAndDoTask()" that are
made from the code that deals with the incoming request will (at least in the theoretical
model) never return to their caller and the thread will continue to execute in a different
context that is&amp;nbsp;"TBD" at the time of the call. By the time the call stack is
unwound and the&amp;nbsp;initiating call (like FindCustomer) indeed returns, the request
is therefore fully processed and the caller&amp;nbsp;may not&amp;nbsp;perform any further
actions.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
So the issue at hand is to make that fact clear in the programming model. In ASP.NET,
there is a single construct called "Server.Transfer()" for that sort of continuation,
but it's very specific to ASP.NET and requires that the caller knows where you want
to yield control to.&amp;nbsp;In the case I have here, the caller knows that it is surrendering
the thread to some other handler, but it doesn't know to to whom, because this is
dynamically determined by the underlying frameworks. All that's visible and should
be visible in the code is a "normal" method call.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;cs.FindCustomer(customerId)&amp;nbsp;&lt;/font&gt;&lt;font face=Verdana&gt;might
therefore not be a good name, because&amp;nbsp;it looks "too normal". And of course I
don't have the powers to&amp;nbsp;invent a new&amp;nbsp;statement&amp;nbsp;for the C# language
like&amp;nbsp;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;continue(&lt;/strong&gt;cs.FindCustomer(customerId)&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font face=Verdana&gt;&amp;nbsp;that
would result in a continuation that simply doesn't return to the call location. Since
I can't do that, there has to be a different way to flag it. Sure, I could put an
attribute on the method, but Intellisense wouldn't show that, would it? So it seems
the best way is to have a convention of prefixing the method name.&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
There were a bunch of ideas in the comments for method-name prefixes. Here is a selection: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.InitiateFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.YieldFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.YieldToFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.InjectFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.PlaceRequestFindCustomer(customerId)&lt;/font&gt; 
&lt;li&gt;
&lt;font face="Courier New"&gt;cs.PostRequestFindCustomer(customerId)&lt;/font&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I've got most of the&amp;nbsp;underlying&amp;nbsp;correlation and dispatch infrastructure
sitting here, but finding a good&amp;nbsp;programming model for that sort of behavior
is quite difficult. 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;[Of course, this post won't make it on Microsoft Watch,&amp;nbsp;eWeek&amp;nbsp;or The
Register]&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=514bac78-5c4e-4c57-9c15-e7736c83aa1d" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,514bac78-5c4e-4c57-9c15-e7736c83aa1d.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology</category>
      <category>Technology/ASP.NET</category>
      <category>Technology/CLR</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=df15d983-cb2f-412d-8efc-83f1447b0a83</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,df15d983-cb2f-412d-8efc-83f1447b0a83.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,df15d983-cb2f-412d-8efc-83f1447b0a83.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=df15d983-cb2f-412d-8efc-83f1447b0a83</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The recording of last week's .NET Rocks show on which I explained my view on the "services
mindset" (at 4AM in the morning) is now available for download from <a href="http://www.franklins.net/dotnetrocks/">franklins.net</a></p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=df15d983-cb2f-412d-8efc-83f1447b0a83" />
      </body>
      <title>.NET Rocks Recording posted</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,df15d983-cb2f-412d-8efc-83f1447b0a83.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/19/NET+Rocks+Recording+Posted.aspx</link>
      <pubDate>Mon, 19 Jul 2004 07:07:26 GMT</pubDate>
      <description>&lt;p&gt;
The recording of last week's .NET Rocks show on which I explained my view on the&amp;nbsp;"services
mindset" (at 4AM in the morning) is now available for download&amp;nbsp;from&amp;nbsp;&lt;a href="http://www.franklins.net/dotnetrocks/"&gt;franklins.net&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=df15d983-cb2f-412d-8efc-83f1447b0a83" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,df15d983-cb2f-412d-8efc-83f1447b0a83.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=6215302e-b279-4e35-96ab-fc4d9bd4eedc</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,6215302e-b279-4e35-96ab-fc4d9bd4eedc.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,6215302e-b279-4e35-96ab-fc4d9bd4eedc.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=6215302e-b279-4e35-96ab-fc4d9bd4eedc</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <div class="Section1">
          <p>
newtelligence AG will be hosting an open <a href="http://www.newtelligence.net/PermaLink.aspx?guid=c9fd0897-8702-4e1b-8aa9-2dbcf66051b4">workshop</a> on
service-oriented development, covering principles, architecture ideas and implementation
guidance on October 13-15 in Düsseldorf, Germany. 
</p>
          <p>
The workshop will be held in English, will be hosted by my partner and “Mr.
Methodologies” Achim Oellers and myself, and is limited to just 15 (!) attendees
to assure an interactive environment that maximizes everyone’s benefit. The
cap on the number of attendees also allows us to adjust the content to individual
needs to some extent. 
</p>
          <p>
We will cover the “services philosophy” and theoretical foundations of
service-compatible transaction techniques, scalability and federation patterns, autonomy
and other important aspects. And once we’ve shared our “services mind-set”,
we will take the participants on a very intense “guided tour” through
(a lot of) very real and production-level quality code (including the Proseware example
application that newtelligence built for Microsoft Corporation) that turns the theory
to practice on the Windows platform and shows that there’s no need to wait for
some shiny future technology to come out in 2 year’s time to benefit from services
today. 
</p>
          <p>
Regular pricing for the event is €2500.00 (plus applicable taxes) and includes: 
</p>
          <ul>
            <li>
              <div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in">3-day workshop in English from
9:00 – 18:00 (or later depending on topic/evening) 
</div>
            </li>
            <li>
              <div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in">
                <span style="FONT-FAMILY: Symbol">
                  <span style="FONT: 7pt 'Times New Roman'"> </span>
                </span>2
nights hotel stay (Oct 13<sup>th</sup> and 14<sup>th</sup>) 
</div>
            </li>
            <li>
              <div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in">Group dinner with the experts
on the first night.  The 2<sup>nd</sup> night is at your disposal to enjoy Düsseldorf’s
fabulous Altstadt at your own leisure 
</div>
            </li>
            <li>
              <div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in">Lunch (and snacks/drinks throughout
the day) 
</div>
            </li>
            <li>
              <div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in">Printed materials (in English),
as appropriate 
</div>
            </li>
            <li>
              <div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in">Post-Workshop CD containing
all presentations and materials used/shown 
</div>
            </li>
          </ul>
          <p>
For registration inquiries, information about the prerequisites, as well as for group
and early-bird discount options, please contact Mr. Fons Habes via <a href="mailto:training@newtelligence.com">training@newtelligence.com</a>.
If the event is sold out at the time of your inquiry or if you are busy on this date,
we will be happy to pre-register you for one of the upcoming event dates or arrange
for an event at your site.
</p>
        </div>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=6215302e-b279-4e35-96ab-fc4d9bd4eedc" />
      </body>
      <title>A word from us, my sponsor: newtelligence SOA Workshop in Düsseldorf, October 13-15 2004</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,6215302e-b279-4e35-96ab-fc4d9bd4eedc.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/16/A+Word+From+Us+My+Sponsor+Newtelligence+SOA+Workshop+In+D%c3%bcsseldorf+October+1315+2004.aspx</link>
      <pubDate>Fri, 16 Jul 2004 11:09:22 GMT</pubDate>
      <description>&lt;div class=Section1&gt;
&lt;p&gt;
newtelligence AG will be hosting an open &lt;a href="http://www.newtelligence.net/PermaLink.aspx?guid=c9fd0897-8702-4e1b-8aa9-2dbcf66051b4"&gt;workshop&lt;/a&gt; on
service-oriented development, covering principles, architecture ideas and implementation
guidance on October 13-15 in D&amp;#252;sseldorf, Germany. 
&lt;/p&gt;
&lt;p&gt;
The workshop will be held in English, will be hosted by my partner and &amp;#8220;Mr.
Methodologies&amp;#8221; Achim Oellers and myself, and is limited to just 15 (!) attendees
to assure an interactive environment that maximizes everyone&amp;#8217;s benefit. The
cap on the number of attendees also allows us to adjust the content to individual
needs to some extent. 
&lt;/p&gt;
&lt;p&gt;
We will cover the &amp;#8220;services philosophy&amp;#8221; and theoretical foundations of
service-compatible transaction techniques, scalability and federation patterns, autonomy
and other important aspects. And once we&amp;#8217;ve shared our &amp;#8220;services mind-set&amp;#8221;,
we will take the participants on a very intense &amp;#8220;guided tour&amp;#8221; through
(a lot of) very real and production-level quality code (including the Proseware example
application that newtelligence built for Microsoft Corporation) that turns the theory
to practice on the Windows platform and shows that there&amp;#8217;s no need to wait for
some shiny future technology to come out in 2 year&amp;#8217;s time to benefit from services
today. 
&lt;/p&gt;
&lt;p&gt;
Regular pricing for the event is &amp;#8364;2500.00 (plus applicable taxes) and includes: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in"&gt;3-day workshop in English from
9:00 &amp;#8211; 18:00 (or later depending on topic/evening)&amp;nbsp;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in"&gt;&lt;span style="FONT-FAMILY: Symbol"&gt;&lt;span style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;2
nights hotel stay (Oct 13&lt;sup&gt;th&lt;/sup&gt; and 14&lt;sup&gt;th&lt;/sup&gt;) 
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in"&gt;Group dinner with the experts
on the first night. &amp;nbsp;The 2&lt;sup&gt;nd&lt;/sup&gt; night is at your disposal to enjoy D&amp;#252;sseldorf&amp;#8217;s
fabulous Altstadt at your own leisure 
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in"&gt;Lunch (and snacks/drinks throughout
the day) 
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in"&gt;Printed materials (in English),
as appropriate 
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in"&gt;Post-Workshop CD containing
all presentations and materials used/shown 
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
For registration inquiries, information about the prerequisites, as well as for group
and early-bird discount options, please contact Mr. Fons Habes via &lt;a href="mailto:training@newtelligence.com"&gt;training@newtelligence.com&lt;/a&gt;.
If the event is sold out at the time of your inquiry or if you are busy on this date,
we will be happy to pre-register you for one of the upcoming event dates or arrange
for an event at your site.
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=6215302e-b279-4e35-96ab-fc4d9bd4eedc" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,6215302e-b279-4e35-96ab-fc4d9bd4eedc.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>newtelligence</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=1214e26d-674e-4a5c-b716-eaa07d327705</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,1214e26d-674e-4a5c-b716-eaa07d327705.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,1214e26d-674e-4a5c-b716-eaa07d327705.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=1214e26d-674e-4a5c-b716-eaa07d327705</wfw:commentRss>
      <slash:comments>23</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
We have a bit of a wording problem. With what I am current building we have a
bit (not precisely) a notion of "<a href="http://www.sidhe.org/~dan/blog/archives/000211.html">tail
calls</a>". Here's an example:
</p>
        <font color="#0000ff" size="4">
          <p>
            <font face="Courier New" size="2">public</font>
          </p>
        </font>
        <font face="Courier New">
          <font color="#000000">
          </font>
          <font color="#0000ff">void</font>
          <font color="#000000"> LookupMessage(int
messageId)<br /></font>
        </font>
        <font face="Courier New">{<br />
   </font>
        <font face="Courier New">MessageStoreService messageStore = <font color="#0000ff">new</font></font>
        <font size="4">
          <font face="Courier New" size="2"> MessageStoreService();<br />
   </font>
          <font face="Courier New" size="2">messageStore.LookupMessage(messageId);<br /></font>
          <font face="Courier New" size="2">}</font>
        </font>
        <p>
          <font size="4">
            <font size="2">The call to LookupMessage() doesn't return anything
as a return value or through output parameters. Instead, the resulting reply
message surfaces moments later at a totally different place within the same application.
At the same time, the object with the method you see here, surrenders all control
to the (anonymous) receiver of the reply. It's a tiny bit like Server.Transfer() in
ASP.NET.</font>
          </font>
        </p>
        <p>
          <font size="4">
            <font size="2">So the naming problem is that neither of "GetMessage()",
"LookupMessage()", "RequestMessage()" sounds right and they all look odd if there's
no request/response pattern. The current favorite is to prefix all such methods with
"Yield" so that we'd have "YieldLookupMessage()". Or "LookupMessageAndYield()"? Or
something else? </font>
          </font>
        </p>
        <p>
          <font size="4">
            <font size="2">
              <em>Update:</em> Also consider this</font>
          </font>
        </p>
        <p>
          <font size="4">
            <font face="Courier New">
              <font size="2">public<font color="#000000"></font><font color="#0000ff">void</font></font>
            </font>
            <font face="Courier New">
              <font size="2">
                <font color="#000000"> LookupCustomer(int
customerId)<br /></font>{<br />
   CustomerService cs = <font color="#0000ff">new</font></font>
            </font>
            <font face="Courier New" size="2"> CustomerService();<br />
   </font>
            <font size="2">
              <font face="Courier New">cs.FindCustomer(customerId);<br /></font>
              <font face="Courier New">}</font>
            </font>
          </font>
        </p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1214e26d-674e-4a5c-b716-eaa07d327705" />
      </body>
      <title>Looking for a word here ....</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,1214e26d-674e-4a5c-b716-eaa07d327705.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/15/Looking+For+A+Word+Here.aspx</link>
      <pubDate>Thu, 15 Jul 2004 11:17:41 GMT</pubDate>
      <description>&lt;p&gt;
We&amp;nbsp;have a bit of a wording problem. With what I am current building we have a
bit (not precisely)&amp;nbsp;a notion of "&lt;a href="http://www.sidhe.org/~dan/blog/archives/000211.html"&gt;tail
calls&lt;/a&gt;". Here's an example:
&lt;/p&gt;
&lt;font color=#0000ff size=4&gt; 
&lt;p&gt;
&lt;font face="Courier New" size=2&gt;public&lt;/font&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt;&lt;font color=#000000&gt; LookupMessage(int
messageId)&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New"&gt;MessageStoreService messageStore = &lt;font color=#0000ff&gt;new&lt;/font&gt;&lt;/font&gt;&lt;font size=4&gt;&lt;font face="Courier New" size=2&gt; MessageStoreService();&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New" size=2&gt;messageStore.LookupMessage(messageId);&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New" size=2&gt;}&lt;/font&gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font size=2&gt;The call to LookupMessage() doesn't return anything as a
return value or through output parameters. Instead,&amp;nbsp;the resulting reply message
surfaces moments later at a totally different place within the same application. At
the same time, the object with the method you see here, surrenders all control to
the (anonymous) receiver of the reply. It's a tiny bit like Server.Transfer() in ASP.NET.&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font size=2&gt;So the naming problem is that neither of "GetMessage()",
"LookupMessage()", "RequestMessage()" sounds right and they all look odd if there's
no request/response pattern. The current favorite is to prefix all such methods with
"Yield" so that we'd have "YieldLookupMessage()". Or "LookupMessageAndYield()"? Or
something else? &lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font size=2&gt;&lt;em&gt;Update:&lt;/em&gt; Also consider this&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;public&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt; LookupCustomer(int
customerId)&lt;br&gt;
&lt;/font&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp; CustomerService&amp;nbsp;cs = &lt;font color=#0000ff&gt;new&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt; CustomerService();&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;cs.FindCustomer(customerId);&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;}&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&gt;&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1214e26d-674e-4a5c-b716-eaa07d327705" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,1214e26d-674e-4a5c-b716-eaa07d327705.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=c9e5630a-bf19-4187-b85b-cc825c6450c9</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,c9e5630a-bf19-4187-b85b-cc825c6450c9.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,c9e5630a-bf19-4187-b85b-cc825c6450c9.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=c9e5630a-bf19-4187-b85b-cc825c6450c9</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Carl invited me for <a href="http://www.franklins.net/calldotnetrocks/">.NET Rocks</a> on
Thursday night. That is July 15th, 10 PM-Midnight Eastern Standard Time (U.S.) which
is <strong>FOUR A.M. UNTIL SIX A.M.</strong> Central European Time (CET) on Friday
morning. I am not sure whether my brain can properly operate at that time. The most
fun thing would be to go out drinking Thursday night ;-)   I want to talk
about <em>(guess what)</em> Services. Not Indigo, not WSE, not Enterprise Services,
not SOAP, not XML. Services. Mindset first, tools later.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=c9e5630a-bf19-4187-b85b-cc825c6450c9" />
      </body>
      <title>An early, early morning for the .NET Rocks Show</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,c9e5630a-bf19-4187-b85b-cc825c6450c9.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/13/An+Early+Early+Morning+For+The+NET+Rocks+Show.aspx</link>
      <pubDate>Tue, 13 Jul 2004 19:53:18 GMT</pubDate>
      <description>&lt;p&gt;
Carl invited me for &lt;a href="http://www.franklins.net/calldotnetrocks/"&gt;.NET Rocks&lt;/a&gt; on
Thursday night. That is July 15th, 10 PM-Midnight Eastern Standard Time (U.S.) which
is &lt;strong&gt;FOUR A.M. UNTIL SIX A.M.&lt;/strong&gt;&amp;nbsp;Central European Time (CET) on Friday
morning. I am not sure whether my brain can properly operate at that time. The most
fun thing would be to go out drinking Thursday night ;-)&amp;nbsp;&amp;nbsp; I want to talk
about &lt;em&gt;(guess what)&lt;/em&gt; Services.&amp;nbsp;Not Indigo, not WSE, not Enterprise Services,
not SOAP, not XML. Services. Mindset first, tools later.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=c9e5630a-bf19-4187-b85b-cc825c6450c9" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,c9e5630a-bf19-4187-b85b-cc825c6450c9.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=f3ee8c60-c912-4c6e-ae5d-7179bf4a879b</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,f3ee8c60-c912-4c6e-ae5d-7179bf4a879b.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,f3ee8c60-c912-4c6e-ae5d-7179bf4a879b.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=f3ee8c60-c912-4c6e-ae5d-7179bf4a879b</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've had several <a href="http://dictionary.reference.com/search?q=epiphany">epiphanies</a> in
the 12 months or so. I don't know how it is for other people, but the way my
thinking evolves is that I've got some inexpressible "thought clouds" going around
in my head for months that I can't really get on paper or talk about in any coherent
way. And then, at some point, there's some catalyst and "bang", it all comes together
and suddenly those clouds start raining ideas and my thinking very rapidly goes through
an actual paradigm shift. 
</p>
        <p>
The first important epiphany occurred when <a href="http://www.thearchitectexchange.com/asehmi">Arvindra</a> gave
me a compact explanation of his very pragmatic view on Agent Technology and Queueing
Networks, which booted the FABRIQ effort. Once I saw what Arvindra had done in
his previous projects and I put that together with my thinking about services,
a lot of things clicked. The insight that formed from there was that
RPC'ish request/response interactions are very restrictive exceptions in a much
larger picture where one-way messages and much more complex message flow-patterns
possibly involving an arbitrary number of parties are the norm. 
</p>
        <p>
The second struck me <em>while on stage</em> in Amsterdam and during the "<a href="http://www.t-kramer.de/album/teched2004/pages/06290030.htm">The
Nerd, The Suit, and the Fortune Teller</a>" play as <a href="http://www.pathelland.com">Pat</a> and
myself were discussing Service Oriented User Interaction. (You need to understand
that we had very limited time for preparation and hence we had a good outline,
but the rest of the script essentially said "go with the flow" and so most
of it was pure improvisation theater). The insight that formed can (with all
due respect) be shortened "the user is just another service". Not only users
shall drive the interaction by issuing messages (commands) to a systems for which
they expect one or more out of a set of possible replies, but there should
also be a way how systems can be drive an interaction by issuing messages to
users expecting one or more out of a set of possible replies. There is no good
reason why any of these two directions of driving the interaction should receive
preferred treatment. There is no client and there is no server. There are just roles
in interactions. That moment, the 3-layer/3-tier model of building applications
died a quick and painless death in my head. I think I have a new one, but
the clouds are still raining ideas. Too early for details. Come back and
ask in a few months.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=f3ee8c60-c912-4c6e-ae5d-7179bf4a879b" />
      </body>
      <title>Epiphanies</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,f3ee8c60-c912-4c6e-ae5d-7179bf4a879b.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/12/Epiphanies.aspx</link>
      <pubDate>Mon, 12 Jul 2004 13:07:23 GMT</pubDate>
      <description>&lt;p&gt;
I've had several &lt;a href="http://dictionary.reference.com/search?q=epiphany"&gt;epiphanies&lt;/a&gt; in
the&amp;nbsp;12 months or so. I don't know how it is for other people, but the way my
thinking evolves is that I've got some inexpressible "thought clouds" going around
in my head for months that I can't really get on paper or talk about in any coherent
way. And then, at some point, there's some catalyst and "bang", it all comes together
and suddenly those clouds start raining ideas and my thinking very rapidly goes through
an actual paradigm shift. 
&lt;/p&gt;
&lt;p&gt;
The first&amp;nbsp;important epiphany&amp;nbsp;occurred when &lt;a href="http://www.thearchitectexchange.com/asehmi"&gt;Arvindra&lt;/a&gt;&amp;nbsp;gave
me a compact explanation of his very pragmatic view on Agent Technology and Queueing
Networks, which booted the FABRIQ effort. Once&amp;nbsp;I saw what Arvindra had done in
his previous projects and I put that together with&amp;nbsp;my&amp;nbsp;thinking about services,
a lot of things clicked.&amp;nbsp;The&amp;nbsp;insight that&amp;nbsp;formed from there was&amp;nbsp;that
RPC'ish request/response interactions are very restrictive exceptions&amp;nbsp;in a much
larger picture where one-way messages and much more complex message flow-patterns
possibly involving&amp;nbsp;an arbitrary number of&amp;nbsp;parties are the norm. 
&lt;/p&gt;
&lt;p&gt;
The second struck me&amp;nbsp;&lt;em&gt;while on stage&lt;/em&gt; in Amsterdam and during the "&lt;a href="http://www.t-kramer.de/album/teched2004/pages/06290030.htm"&gt;The
Nerd, The Suit, and the Fortune Teller&lt;/a&gt;" play as &lt;a href="http://www.pathelland.com"&gt;Pat&lt;/a&gt; and
myself&amp;nbsp;were discussing&amp;nbsp;Service Oriented User Interaction. (You need to understand
that we had&amp;nbsp;very limited time for preparation and hence we had a good outline,
but the rest of the script&amp;nbsp;essentially said&amp;nbsp;"go with the flow" and so&amp;nbsp;most
of it was pure improvisation theater). The insight that formed&amp;nbsp;can (with all
due respect) be shortened&amp;nbsp;"the user is just another service". Not only users
shall drive the interaction by issuing messages (commands) to a systems for which
they expect&amp;nbsp;one or more out of a set of&amp;nbsp;possible replies, but there should
also be a way how systems can be drive an interaction&amp;nbsp;by issuing messages to
users expecting&amp;nbsp;one or more out of a set of possible replies. There is no good
reason why any of these two directions of driving&amp;nbsp;the interaction should receive
preferred treatment. There is no client and there is no server. There are just roles
in interactions.&amp;nbsp;That moment, the 3-layer/3-tier model of building applications
died a&amp;nbsp;quick and painless&amp;nbsp;death in my head. I think I have a new one, but
the clouds are still raining ideas. Too early&amp;nbsp;for details.&amp;nbsp;Come back and
ask in a few months.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=f3ee8c60-c912-4c6e-ae5d-7179bf4a879b" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,f3ee8c60-c912-4c6e-ae5d-7179bf4a879b.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=1837f563-00ae-40e2-a009-03656d29a20f</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,1837f563-00ae-40e2-a009-03656d29a20f.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,1837f563-00ae-40e2-a009-03656d29a20f.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=1837f563-00ae-40e2-a009-03656d29a20f</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <div class="Section1">
          <p>
In my <a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=ad978cf4-5786-436b-a4ac-3faf9ed3b30d">comment
view for the last post (comment #1)</a>, Piyush Pant writes about the confusion around
different pipeline models and frameworks that are popping up all over the place and
mentions Proseware, so I need to clarify some things:
</p>
          <p>
I'll address the "too many frameworks" concern first: Proseware's explicit design
goal and my job was to use the technologies ASP.NET Web Services, WSE 2.0, IIS, MSMQ,
and Enterprise Services as pure as possible and I did intentionally not introduce
yet another framework for the runtime bits beyond a few utility classes used by the
services as a common infrastructure (like a config-driven web service proxy factory,
the queue listener, or the just-in-time activation proxy pooling). What my job was
and what I reasonably succeeded at was to show that:
</p>
          <p style="MARGIN-LEFT: 0.5in">
            <i>Writing Service Oriented Applications on today's Windows Server 2003 platform does
not require yet another framework. </i>
          </p>
          <p>
The framework'ish pieces that I had to add are simply addressing some deployment issues
like creating accounts, setting ACLs or setting up databases, that need to be done
in a "real" app hat isn't a toy. Such things are sometimes difficult to abstract on
the level of what the .NET Framework can offer as a general-purpose platform or are
simply not there yet. All of these extra classes reside in an isolated assembly that's
only used by the installers.
</p>
          <p>
The total number of utility classes that play a role of any importance at runtime
is 5 (in words <i>five</i>) and none of them has more than three screen pages worth
of actual code. Let me repeat:
</p>
          <p style="MARGIN-LEFT: 0.5in">
            <i>Writing Service Oriented Applications on today's Windows Server 2003 platform does
not require yet another framework. </i>
          </p>
          <p>
I <i>do</i> have a dormant (newtelligence-owned) code branch sitting here that'd make
a lot of things in Proseware easier and more elegant to develop and makes reconfiguring
services more convenient, but it's a developer convenience and productivity framework.
No pipelines, no other architecture, just a prettier shell around the exact Proseware
architecture and technologies I chose. 
</p>
          <p>
To illustrate my point about the fact that we don't need another entirely new framework,
I have here (<a href="http://staff.newtelligence.net/clemensv/content/binary/MessageQueueWebRequest.cs.txt">MessageQueueWebRequest.cs.txt</a>, <a href="http://staff.newtelligence.net/clemensv/content/binary/MessageQueueWebResponse.cs.txt">MessageQueueWebResponse.cs.txt</a>)
an early 0.1 prototype copy of our MessageQueueWebRequest/-WebResponse class pair
that supports sending WS messages through MSMQ. (That prototype only does very simple
one-way messages; you can do a lot more with MSMQ).  
</p>
          <p>
Take the code, put it in yours, create a private queue, take an arbitrary ASMX WebService
proxy, call <i>MessageQueueWebRequest.RegisterMSMQProtocol()</i> when your app starts,
instantiate the proxy, set the Url property of the proxy to <i>msmq://mymachine/private$/myqueue, </i>invoke
the proxy and watch how a SOAP message materializes in the queue. 
</p>
          <p>
Next step: use a WSE proxy. Works too. I'll leave the receiver logic to your imagination,
but that's not really much more than listening to the queue and throwing the message
into a WSE 2.0 SoapMethod or throwing it as a raw HTTP request at an ASMX WebMethod
or by using a SimpleWorkerRequest on a self-hosted ASP.NET AppDomain (just like WebMatrix's
Cassini hosts that stuff).
</p>
          <p>
 
</p>
          <p>
On to "pipelines" in the same context: Pipelines are a very common design pattern
and you can find hundreds of variations of them in many projects (likely dozens from
MS) which all have some sort of a notion of a pipeline. It's just "pipeline", not <i>Pipeline(tm)
2003 SP1</i>. 
</p>
          <p>
User-extensible pipeline models are a nice idea, but I don't think they are very useful
to have or consider for most services of the type that Proseware has (and that covers
a lot of types). 
</p>
          <p>
Frankly, most things that are done with pipelines in generalized architectures that
wrap around endpoints (in/out crosscutting pipelines) and that are not about <b>"logging"</b> (which
is, IMHO, more useful if done explicitly and in-context) are already in the existing
technology stack (Enterprise Services, WSE) or are really jobs for other services. 
</p>
          <p>
There is no need to invent another pipeline to process custom headers in ASMX, if
you have SoapExtensions. There is no need to invent a new pipeline model to do WS-Security,
if you can plug the WSE 2.0 pipeline into the ASMX SoapExtension pipeline already.
There is no need to invent a new pipeline model to push a new transaction context
on the stack, if you can hook the COM+ context pipeline into your call chain by using
ES. There is no need to invent another pipeline for authorization, if you can hook
arbitrary custom stuff into the ASP.NET Http Pipeline or the WSE 2.0 pipeline already
has or simply use what the ES context pipeline gives you. 
</p>
          <p>
I just enumerated four (!) different pipeline models and all of them are in the bits
you already have on a shipping platform today and as it happens, all of them compose
really well with each other. The fact that I am writing this might show that most
of us just use and configure their services without even thinking of them as a composite
pipeline model. 
</p>
          <p style="MARGIN-LEFT: 0.5in">
            <i>"We don't need another Pipeline" (I want Tina Turner to sing that for me).</i>
          </p>
          <p>
Of course there's other pipeline jobs, right? Mapping! 
</p>
          <p>
Well, mapping between schemas is something that goes against the notion of a well-defined
contract of a service. Either you have a well-defined contract or two or three or
you don't. If you have a well-defined contract and there's a sender that doesn't adhere
to it, it's the job of another service to provide that sort of data negotiation, because
that's a business-logic task in and by itself.
</p>
          <p>
Umm ... ah! Validation!
</p>
          <p>
That might be true if schema validation is enough, but validation of data is a business
logic level task if things get more complex (like if you need to check a PO against
your catalog and need to check whether that customer is actually entitled to get a
certain discount bracket). That's not a cross-cutting concern. That's a core job of
the app.
</p>
          <p style="MARGIN-LEFT: 0.5in">
            <i>Pipelines are for plumbers</i>
          </p>
          <p style="MARGIN-LEFT: 0.5in">
 
</p>
          <p>
Now, before I confuse everyone (and because Piyush mentioned it explicitly): 
</p>
          <p>
FABRIQ is a wholly different ballgame, because it is precisely a <i>specialized architecture</i> for
dynamically distributable, queued<b></b>(pull-model), one-way <i>pipeline</i> message
processing and that does require a bit of a framework, because the platform doesn't
readily support it. 
</p>
          <p>
We don't really have a notion of an endpoint in FABRIQ that is the default terminal
for any message arriving at a node. We just let stuff asynchronously flow in one direction
and across machines and handlers can choose to look at, modify, absorb or yield resultant
messages into the pipeline as a result of what they do. In that model, the pipeline <b><i>is</i></b> the
application. Very different story, very different sets of requirements, very different
optimization potential and not really about services in the first place (although
we stick to the tenets), but rather about distributing work dynamically and about
doing so as fast as we can make it go.
</p>
          <p>
Sorry, Piyush! All of that totally wasn't going against your valued comments, but
you threw a lit match into a very dry haystack. 
</p>
          <p>
 
</p>
        </div>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1837f563-00ae-40e2-a009-03656d29a20f" />
      </body>
      <title>Pipelines, Pipelines, Pipelines, and Frameworks. A spontaneous rant.</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,1837f563-00ae-40e2-a009-03656d29a20f.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/07/Pipelines+Pipelines+Pipelines+And+Frameworks+A+Spontaneous+Rant.aspx</link>
      <pubDate>Wed, 07 Jul 2004 14:52:10 GMT</pubDate>
      <description>&lt;div class=Section1&gt;
&lt;p&gt;
In my &lt;a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=ad978cf4-5786-436b-a4ac-3faf9ed3b30d"&gt;comment
view for the last post (comment #1)&lt;/a&gt;, Piyush Pant writes about the confusion around
different pipeline models and frameworks that are popping up all over the place and
mentions Proseware, so I need to clarify some things:
&lt;/p&gt;
&lt;p&gt;
I'll address the "too many frameworks" concern first: Proseware's explicit design
goal and my job was to use the technologies ASP.NET Web Services, WSE 2.0, IIS, MSMQ,
and Enterprise Services as pure as possible and I did intentionally not introduce
yet another framework for the runtime bits beyond a few utility classes used by the
services as a common infrastructure (like a config-driven web service proxy factory,
the queue listener, or the just-in-time activation proxy pooling). What my job was
and what I reasonably succeeded at was to show that:
&lt;/p&gt;
&lt;p style="MARGIN-LEFT: 0.5in"&gt;
&lt;i&gt;Writing Service Oriented Applications on today's Windows Server 2003 platform does
not require yet another framework. &lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
The framework'ish pieces that I had to add are simply addressing some deployment issues
like creating accounts, setting ACLs or setting up databases, that need to be done
in a "real" app hat isn't a toy. Such things are sometimes difficult to abstract on
the level of what the .NET Framework can offer as a general-purpose platform or are
simply not there yet. All of these extra classes reside in an isolated assembly that's
only used by the installers.
&lt;/p&gt;
&lt;p&gt;
The total number of utility classes that play a role of any importance at runtime
is 5 (in words &lt;i&gt;five&lt;/i&gt;) and none of them has more than three screen pages worth
of actual code. Let me repeat:
&lt;/p&gt;
&lt;p style="MARGIN-LEFT: 0.5in"&gt;
&lt;i&gt;Writing Service Oriented Applications on today's Windows Server 2003 platform does
not require yet another framework. &lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
I &lt;i&gt;do&lt;/i&gt; have a dormant (newtelligence-owned) code branch sitting here that'd make
a lot of things in Proseware easier and more elegant to develop and makes reconfiguring
services more convenient, but it's a developer convenience and productivity framework.
No pipelines, no other architecture, just a prettier shell around the exact Proseware
architecture and technologies I chose. 
&lt;/p&gt;
&lt;p&gt;
To illustrate my point about the fact that we don't need another entirely new framework,
I have here&amp;nbsp;(&lt;a href="http://staff.newtelligence.net/clemensv/content/binary/MessageQueueWebRequest.cs.txt"&gt;MessageQueueWebRequest.cs.txt&lt;/a&gt;, &lt;a href="http://staff.newtelligence.net/clemensv/content/binary/MessageQueueWebResponse.cs.txt"&gt;MessageQueueWebResponse.cs.txt&lt;/a&gt;)
an early 0.1 prototype copy of our MessageQueueWebRequest/-WebResponse class pair
that supports sending WS messages through MSMQ. (That prototype only does very simple
one-way messages; you can do a lot more with MSMQ). &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Take the code, put it in yours, create a private queue, take an arbitrary ASMX WebService
proxy, call &lt;i&gt;MessageQueueWebRequest.RegisterMSMQProtocol()&lt;/i&gt; when your app starts,
instantiate the proxy, set the Url property of the proxy to &lt;i&gt;msmq://mymachine/private$/myqueue, &lt;/i&gt;invoke
the proxy and watch how a SOAP message materializes in the queue. 
&lt;/p&gt;
&lt;p&gt;
Next step: use a WSE proxy. Works too. I'll leave the receiver logic to your imagination,
but that's not really much more than listening to the queue and throwing the message
into a WSE 2.0 SoapMethod or throwing it as a raw HTTP request at an ASMX WebMethod
or by using a SimpleWorkerRequest on a self-hosted ASP.NET AppDomain (just like WebMatrix's
Cassini hosts that stuff).
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
On to "pipelines" in the same context: Pipelines are a very common design pattern
and you can find hundreds of variations of them in many projects (likely dozens from
MS) which all have some sort of a notion of a pipeline. It's just "pipeline", not &lt;i&gt;Pipeline(tm)
2003 SP1&lt;/i&gt;. 
&lt;/p&gt;
&lt;p&gt;
User-extensible pipeline models are a nice idea, but I don't think they are very useful
to have or consider for most services of the type that Proseware has (and that covers
a lot of types). 
&lt;/p&gt;
&lt;p&gt;
Frankly, most things that are done with pipelines in generalized architectures that
wrap around endpoints (in/out crosscutting pipelines) and that are not about &lt;b&gt;"logging"&lt;/b&gt; (which
is, IMHO, more useful if done explicitly and in-context) are already in the existing
technology stack (Enterprise Services, WSE) or are really jobs for other services. 
&lt;/p&gt;
&lt;p&gt;
There is no need to invent another pipeline to process custom headers in ASMX, if
you have SoapExtensions. There is no need to invent a new pipeline model to do WS-Security,
if you can plug the WSE 2.0 pipeline into the ASMX SoapExtension pipeline already.
There is no need to invent a new pipeline model to push a new transaction context
on the stack, if you can hook the COM+ context pipeline into your call chain by using
ES. There is no need to invent another pipeline for authorization, if you can hook
arbitrary custom stuff into the ASP.NET Http Pipeline or the WSE 2.0 pipeline already
has or simply use what the ES context pipeline gives you. 
&lt;/p&gt;
&lt;p&gt;
I just enumerated four (!) different pipeline models and all of them are in the bits
you already have on a shipping platform today and as it happens, all of them compose
really well with each other. The fact that I am writing this might show that most
of us just use and configure their services without even thinking of them as a composite
pipeline model. 
&lt;/p&gt;
&lt;p style="MARGIN-LEFT: 0.5in"&gt;
&lt;i&gt;"We don't need another Pipeline" (I want Tina Turner to sing that for me).&lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
Of course there's other pipeline jobs, right? Mapping! 
&lt;/p&gt;
&lt;p&gt;
Well, mapping between schemas is something that goes against the notion of a well-defined
contract of a service. Either you have a well-defined contract or two or three or
you don't. If you have a well-defined contract and there's a sender that doesn't adhere
to it, it's the job of another service to provide that sort of data negotiation, because
that's a business-logic task in and by itself.
&lt;/p&gt;
&lt;p&gt;
Umm ... ah! Validation!
&lt;/p&gt;
&lt;p&gt;
That might be true if schema validation is enough, but validation of data is a business
logic level task if things get more complex (like if you need to check a PO against
your catalog and need to check whether that customer is actually entitled to get a
certain discount bracket). That's not a cross-cutting concern. That's a core job of
the app.
&lt;/p&gt;
&lt;p style="MARGIN-LEFT: 0.5in"&gt;
&lt;i&gt;Pipelines are for plumbers&lt;/i&gt;
&lt;/p&gt;
&lt;p style="MARGIN-LEFT: 0.5in"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Now, before I confuse everyone (and because Piyush mentioned it explicitly): 
&lt;/p&gt;
&lt;p&gt;
FABRIQ is a wholly different ballgame, because it is precisely a &lt;i&gt;specialized architecture&lt;/i&gt; for
dynamically distributable, queued&lt;b&gt; &lt;/b&gt;(pull-model), one-way &lt;i&gt;pipeline&lt;/i&gt; message
processing and that does require a bit of a framework, because the platform doesn't
readily support it. 
&lt;/p&gt;
&lt;p&gt;
We don't really have a notion of an endpoint in FABRIQ that is the default terminal
for any message arriving at a node. We just let stuff asynchronously flow in one direction
and across machines and handlers can choose to look at, modify, absorb or yield resultant
messages into the pipeline as a result of what they do. In that model, the pipeline &lt;b&gt;&lt;i&gt;is&lt;/i&gt;&lt;/b&gt; the
application. Very different story, very different sets of requirements, very different
optimization potential and not really about services in the first place (although
we stick to the tenets), but rather about distributing work dynamically and about
doing so as fast as we can make it go.
&lt;/p&gt;
&lt;p&gt;
Sorry, Piyush! All of that totally wasn't going against your valued comments, but
you threw a lit match into a very dry haystack. 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=1837f563-00ae-40e2-a009-03656d29a20f" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,1837f563-00ae-40e2-a009-03656d29a20f.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=ad978cf4-5786-436b-a4ac-3faf9ed3b30d</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,ad978cf4-5786-436b-a4ac-3faf9ed3b30d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,ad978cf4-5786-436b-a4ac-3faf9ed3b30d.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=ad978cf4-5786-436b-a4ac-3faf9ed3b30d</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://benjaminm.net/PermaLink.aspx?guid=87ce6b8b-0fbf-4f0d-86c9-d9e780a1cb6a">Benjamin
Mitchell wrote</a> a better summary of my "Building Proseware Inc." session at TechEd
Amsterdam than I ever could. 
</p>
        <p>
Because ... whenever the lights go on and the mike is open, I somehow automatically
switch into an adrenalin-powered auto-pilot mode that luckily works really
well and since my sessions take up so much energy and "focus on the
moment", I often just don't remember all the things I said once the session is
over and I am cooled down. That also explains why I almost never rehearse sessions
(meaning: I never ever speak to the slides until I face an audience) except when I
have to coordinate with other speakers. Yet, even though most of my sessions are really
ad-hoc performances, whenever I repeat a session I usually remember whatever
I said last time just at the very moment when the respective topic comes up,
so there's an element of routine. It is really strange how that works. That's also
why I am really a bad advisor on how to do sessions the right way, because that is
a very risky approach. I just write slides that provide me with a list of
topics and "illustration helpers" and whatever I say just "happens". 
</p>
        <p>
About Proseware: All the written comments that people submitted after the session
have been collected and are being read and it's very well understood that
you want to get your hands on the bits as soon as possible. One of my big takeaways
from the project is that if you're Microsoft, releasing stuff that is about giving
"how-to" guidance is (for more reasons you can imagine) quite a bit more complicated
than just putting bits up on a download site. It's being worked on. In the meantime,
I'll blog a bit about the patterns I used whenever I can allocate a timeslice.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=ad978cf4-5786-436b-a4ac-3faf9ed3b30d" />
      </body>
      <title>Benjamin's summary of my "Building Proseware" session at TechEd</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,ad978cf4-5786-436b-a4ac-3faf9ed3b30d.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/07/Benjamins+Summary+Of+My+Building+Proseware+Session+At+TechEd.aspx</link>
      <pubDate>Wed, 07 Jul 2004 09:30:13 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://benjaminm.net/PermaLink.aspx?guid=87ce6b8b-0fbf-4f0d-86c9-d9e780a1cb6a"&gt;Benjamin
Mitchell wrote&lt;/a&gt; a better summary of my "Building Proseware Inc." session at TechEd
Amsterdam than I ever could. 
&lt;/p&gt;
&lt;p&gt;
Because ... whenever the lights go on and the mike is open, I somehow automatically
switch into an&amp;nbsp;adrenalin-powered auto-pilot mode that luckily&amp;nbsp;works really
well and since&amp;nbsp;my sessions&amp;nbsp;take up so much energy&amp;nbsp;and "focus on the
moment", I often just don't remember all the things I said&amp;nbsp;once the session is
over and I am cooled down. That also explains why I almost never rehearse sessions
(meaning: I never ever speak to the slides until I face an audience) except when I
have to coordinate with other speakers. Yet, even though most of my sessions are really
ad-hoc performances, whenever I repeat a session I usually&amp;nbsp;remember&amp;nbsp;whatever
I said last time&amp;nbsp;just at the very moment when the respective topic comes up,
so there's an element of routine. It is really strange how that works. That's also
why I am really a bad advisor on how to do sessions the right way, because that is
a very risky approach.&amp;nbsp;I just write slides that provide me with a&amp;nbsp;list of
topics&amp;nbsp;and "illustration helpers" and whatever I say just "happens".&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
About Proseware: All the written comments that people submitted after the session
have been collected and&amp;nbsp;are being&amp;nbsp;read and it's very well understood that
you want to get your hands on the bits as soon as possible. One of my big takeaways
from the project is that if&amp;nbsp;you're Microsoft, releasing stuff that is about giving
"how-to" guidance is (for more reasons you can imagine) quite a bit more complicated
than just putting bits up on a download site. It's being worked on. In the meantime,
I'll blog a bit about the patterns I used whenever I can allocate a timeslice.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=ad978cf4-5786-436b-a4ac-3faf9ed3b30d" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,ad978cf4-5786-436b-a4ac-3faf9ed3b30d.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Talks/TechEd Europe</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=8a119c62-2fc1-4409-9ae4-0b250fdb785b</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,8a119c62-2fc1-4409-9ae4-0b250fdb785b.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,8a119c62-2fc1-4409-9ae4-0b250fdb785b.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=8a119c62-2fc1-4409-9ae4-0b250fdb785b</wfw:commentRss>
      <slash:comments>13</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Simple question: Please show me a case where inheritance and/or full data encapsulation
makes sense for business/domain objects on the implementation level. 
</p>
        <p>
I'll steal the low-hanging fruit: Address. Address is a great candidate when
you look at an OOA model as you could model yourself to death having
BaseAddress(BA) and BA&lt;-StreetAddress(SA) and BA&lt;-PostalAddress(PA) and SA&lt;-US_StreetAddress
and SA&lt;-DE_StreetAddress and SA&lt;-UK_StreetAddress and so forth. 
</p>
        <p>
When it comes to implementation, you'll end up refactoring the class into on thing: <em>Address</em>.
There's probably an <em>AddressType</em> attribute and there's a <em>Country</em> field
that indicates the formatting and since implementing a full address validation component
is way too much work that feature gets cut anyway and hence we end up with a multiline
text field with the properly formatted address and stuff like <em>Street </em>and<em> PostOfficeBox
(</em>eventually<em></em>normalized to<em> AddressField)</em>, <em>City</em>, <em>PostalCode,
Country</em> and <em>Region </em>is<em></em>kept separate really just to make
searching easier and faster. The stuff that goes onto the letter envelope is really
only the preformatted address text.
</p>
        <p>
Maybe I am too much of a data (read: XML, Messages, SQL) guy by now, but I just lost
faith that objects are any good on the "business logic" abstraction level. The whole
inheritance story is usually refactored away for very pragmatic reasons
and the encapsulation story isn't all that useful either. You simply can't pragmatically
regard data validation of data on a property get/set level as a useful general design
pattern, because a type like <em>Address</em> is <strong>one type</strong> with interdependency
between its elements and not simply a container for types. The rules for<em> Region</em> depend
on <em>Country</em> and the rules for <em>AddressField</em> (or <em>Street/PostOfficeBox</em>)
depend on <em>AddressType</em>. Since the object can't know your intent of what data
you want to supply to it on a property get/set level, it can't do meaningful validation
on that level. Hence, you end up calling something like <em>address.Validate() </em>and<em></em>from
there it's really a small step to separate out code and data into a message and a
service that deals with it and call <em>Validate(address). </em>And that sort of service
is the best way to support polymorphism over a scoped set of "classes" because
it can potentially support "any" address schema and can yet concentrate and share all
the validation logic (which is largely the same across whatever format you might choose)
in a single place and not spread it across an array of specialized classes that's
much, much harder to maintain.
</p>
        <p>
What you end up with are elements and attributes (infoset) for the data that flows
across, services that deal with the data that flows, and rows and columns that efficiently
store data and let you retrieve it flexibly and quickly. Objects lost (except on the
abstract and conceptional analysis level where they are useful to understand a problem
space) their place in that picture for me.
</p>
        <p>
While objects are fantastic for frameworks, I've absolutely unlearned why I would
ever want them on the business logic level in practice. Reeducate me.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=8a119c62-2fc1-4409-9ae4-0b250fdb785b" />
      </body>
      <title>Rows and Columns + Elements and Attributes is all you need</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,8a119c62-2fc1-4409-9ae4-0b250fdb785b.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/07/Rows+And+Columns+Elements+And+Attributes+Is+All+You+Need.aspx</link>
      <pubDate>Wed, 07 Jul 2004 06:51:41 GMT</pubDate>
      <description>&lt;p&gt;
Simple question: Please show me a case where inheritance and/or full data encapsulation
makes sense for business/domain objects on the implementation level.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
I'll steal the&amp;nbsp;low-hanging fruit: Address. Address is a great candidate&amp;nbsp;when
you look&amp;nbsp;at an OOA model as you&amp;nbsp;could model yourself to death&amp;nbsp;having
BaseAddress(BA) and BA&amp;lt;-StreetAddress(SA) and BA&amp;lt;-PostalAddress(PA) and SA&amp;lt;-US_StreetAddress
and SA&amp;lt;-DE_StreetAddress and SA&amp;lt;-UK_StreetAddress and so forth. 
&lt;/p&gt;
&lt;p&gt;
When it comes to implementation, you'll end up refactoring the class into on thing: &lt;em&gt;Address&lt;/em&gt;.
There's probably an &lt;em&gt;AddressType&lt;/em&gt; attribute and there's a &lt;em&gt;Country&lt;/em&gt; field
that indicates the formatting and since implementing a full address validation component
is way too much work that feature gets cut anyway and hence we end up with a multiline
text field with the properly formatted address and stuff like &lt;em&gt;Street &lt;/em&gt;and&lt;em&gt; PostOfficeBox
(&lt;/em&gt;eventually&lt;em&gt; &lt;/em&gt;normalized to&lt;em&gt; AddressField)&lt;/em&gt;, &lt;em&gt;City&lt;/em&gt;, &lt;em&gt;PostalCode,
Country&lt;/em&gt;&amp;nbsp;and &lt;em&gt;Region &lt;/em&gt;is&lt;em&gt; &lt;/em&gt;kept separate really just to make
searching easier and faster. The stuff that goes onto the letter envelope is really
only the preformatted address text.
&lt;/p&gt;
&lt;p&gt;
Maybe I am too much of a data (read: XML, Messages, SQL) guy by now, but I just lost
faith that objects are any good on the "business logic" abstraction level. The whole
inheritance story&amp;nbsp;is&amp;nbsp;usually refactored away for very pragmatic reasons
and the encapsulation story isn't all that useful either. You simply can't&amp;nbsp;pragmatically
regard data validation of data on a property get/set level as a useful general design
pattern, because a type like &lt;em&gt;Address&lt;/em&gt; is &lt;strong&gt;one type&lt;/strong&gt; with interdependency
between its elements and not simply a container for types. The&amp;nbsp;rules&amp;nbsp;for&lt;em&gt; Region&lt;/em&gt; depend
on &lt;em&gt;Country&lt;/em&gt; and the rules for &lt;em&gt;AddressField&lt;/em&gt; (or &lt;em&gt;Street/PostOfficeBox&lt;/em&gt;)
depend on &lt;em&gt;AddressType&lt;/em&gt;. Since the object can't know your intent of what data
you want to supply to it on a property get/set level, it can't do meaningful validation
on that level. Hence, you end up calling something like &lt;em&gt;address.Validate() &lt;/em&gt;and&lt;em&gt; &lt;/em&gt;from
there it's really a small step to separate out code and data into a message and a
service that deals with it and call &lt;em&gt;Validate(address). &lt;/em&gt;And that sort of service
is the best way to support polymorphism over a scoped set of "classes"&amp;nbsp;because
it can potentially support "any" address schema and can yet&amp;nbsp;concentrate and&amp;nbsp;share&amp;nbsp;all
the validation logic (which is largely the same across whatever format you might choose)
in a single place and not spread it across an array of specialized classes that's
much, much&amp;nbsp;harder to maintain.
&lt;/p&gt;
&lt;p&gt;
What you end up with are elements and attributes (infoset) for the data that flows
across, services that deal with the data that flows, and rows and columns that efficiently
store data and let you retrieve it flexibly and quickly. Objects lost (except on the
abstract and conceptional analysis level where they are useful to understand a problem
space) their place in that picture for me.
&lt;/p&gt;
&lt;p&gt;
While objects are fantastic for frameworks, I've absolutely unlearned why I would
ever want them on the business logic level in practice. Reeducate me.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=8a119c62-2fc1-4409-9ae4-0b250fdb785b" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,8a119c62-2fc1-4409-9ae4-0b250fdb785b.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=f9d907bd-2c2f-4dc1-8b87-5b7549366bbf</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,f9d907bd-2c2f-4dc1-8b87-5b7549366bbf.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,f9d907bd-2c2f-4dc1-8b87-5b7549366bbf.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=f9d907bd-2c2f-4dc1-8b87-5b7549366bbf</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
We've built FABRIQ, we've built Proseware. We have written seminar series about Web
Services Best Practices and Service Orientation for Microsoft Europe. I speak about
services and aspects of services at conferences around the world. And at all events
where I talk about Services, I keep hearing the same question: "Enough of the theory,
how do I do it?"
</p>
        <p>
Therefore we have <a href="http://www.newtelligence.net/PermaLink.aspx?guid=c9fd0897-8702-4e1b-8aa9-2dbcf66051b4">announced</a> a
seminar/workshop around designing and building service oriented systems that puts
together all the things we've found out in the past years about how services can be
built today and on today's Microsoft technology stack and how your systems can
be designed for with migration to the next generation Microsoft technlogy stack in
mind. Together with our <em>newtelligence Associates</em>, we are offering this workshop
for in-house delivery at client sites world-wide and are planning to announce dates
and locations for central, "open for all" events soon. 
</p>
        <p>
If you are interested in inviting us for an event at your site, contact <a href="mailto:bartd@newtelligence.com">Bart
DePetrillo</a>, or write to <a href="mailto:sales@newtelligence.com">sales@newtelligence.com</a>.
If you are interested in participating at a central seminar, <a href="mailto:bartd@newtelligence.com">Bart</a> would
like to hear about it (no obligations) so that we can select reasonable location(s)
and date(s) that fit your needs.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=f9d907bd-2c2f-4dc1-8b87-5b7549366bbf" />
      </body>
      <title>newtelligence Seminar Series: Service Oriented Architecture and Systems</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,f9d907bd-2c2f-4dc1-8b87-5b7549366bbf.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/05/newtelligence+Seminar+Series+Service+Oriented+Architecture+And+Systems.aspx</link>
      <pubDate>Mon, 05 Jul 2004 07:06:41 GMT</pubDate>
      <description>&lt;p&gt;
We've built FABRIQ, we've built Proseware. We have written seminar series about Web
Services Best Practices and Service Orientation for Microsoft Europe. I speak about
services and aspects of services at conferences around the world. And at all events
where I talk about Services, I keep hearing the same question: "Enough of the theory,
how do I do it?"
&lt;/p&gt;
&lt;p&gt;
Therefore we have &lt;a href="http://www.newtelligence.net/PermaLink.aspx?guid=c9fd0897-8702-4e1b-8aa9-2dbcf66051b4"&gt;announced&lt;/a&gt; a
seminar/workshop around designing and building service oriented systems that puts
together all the things we've found out in the past years about how services can be
built today and on today's Microsoft technology stack and how your&amp;nbsp;systems can
be designed for with migration to the next generation Microsoft technlogy stack in
mind. Together with our &lt;em&gt;newtelligence Associates&lt;/em&gt;, we are offering this workshop
for in-house delivery at client sites world-wide and are planning to announce&amp;nbsp;dates
and locations for central, "open for all"&amp;nbsp;events soon. 
&lt;/p&gt;
&lt;p&gt;
If you are interested in inviting us for an event at your site, contact &lt;a href="mailto:bartd@newtelligence.com"&gt;Bart
DePetrillo&lt;/a&gt;, or write to &lt;a href="mailto:sales@newtelligence.com"&gt;sales@newtelligence.com&lt;/a&gt;.
If you are interested in participating at&amp;nbsp;a central seminar,&amp;nbsp;&lt;a href="mailto:bartd@newtelligence.com"&gt;Bart&lt;/a&gt; would
like to hear about it (no obligations) so that we can&amp;nbsp;select reasonable location(s)
and date(s) that fit your needs.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=f9d907bd-2c2f-4dc1-8b87-5b7549366bbf" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,f9d907bd-2c2f-4dc1-8b87-5b7549366bbf.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Technology/FABRIQ</category>
      <category>Technology/Indigo</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=69800eae-bf3a-4652-b193-a89e32a900e3</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,69800eae-bf3a-4652-b193-a89e32a900e3.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,69800eae-bf3a-4652-b193-a89e32a900e3.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=69800eae-bf3a-4652-b193-a89e32a900e3</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Autonomy means that a service is alive. 
</p>
        <p>
Here are my sub-tenets:
</p>
        <ul>
          <li>
            <strong>It has its very own, independent view on data.</strong> That may or may not
result in fully owning its own data store (I think it should, but that's all a matter
of scale and use case), but it certainly shall never share its own view on a shared store
with others. The service's public interface(s) provide(s) the only way to
manipulate its view on data. 
</li>
          <li>
            <strong>It controls its own lifetime.</strong> It can do periodical tasks, spin its
own threads and should not be forced to shut down because its hosting process
model thinks it's idle for the sole reason that it hasn't seen inbound traffic
for a while.</li>
          <li>
            <strong>It has its own identity and carries a security responsibility.</strong> It identifies
itself with a service-unique principal against other services and through
of its own authorization rules it takes the responsibility upon itself that no user
gains illegitimate access to backend data or services. It identifies and takes responsibility
for those that invoke it, but never assumes their identity.</li>
        </ul>
        <p>
The <a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=3a029ead-58f2-405a-a5d1-6cc3513a59fa">PEACE</a> tenets
for SO are a composite set. Autonomy is architecturally the most far reaching of the SO
tenets and it is much more about the inside and fundamental behavior
of a service than about its edge.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=69800eae-bf3a-4652-b193-a89e32a900e3" />
      </body>
      <title>SO(A): Autonomy</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,69800eae-bf3a-4652-b193-a89e32a900e3.aspx</guid>
      <link>http://vasters.com/clemensv/2004/06/04/SOA+Autonomy.aspx</link>
      <pubDate>Fri, 04 Jun 2004 09:15:08 GMT</pubDate>
      <description>&lt;p&gt;
Autonomy means that a service is alive. 
&lt;/p&gt;
&lt;p&gt;
Here are my sub-tenets:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It has its very own, independent view on data.&lt;/strong&gt; That may or may not
result in fully owning its own data store (I think it should, but that's all a matter
of scale and use case), but it certainly shall never share its own view on a shared&amp;nbsp;store
with others.&amp;nbsp;The service's&amp;nbsp;public interface(s) provide(s) the only way to
manipulate its view on data. 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It controls its own lifetime.&lt;/strong&gt; It can do periodical tasks, spin its
own threads and&amp;nbsp;should not be forced to shut down because its hosting process
model thinks it's idle&amp;nbsp;for the sole reason that it&amp;nbsp;hasn't seen inbound traffic
for a while.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It has its own identity and carries a security responsibility.&lt;/strong&gt; It&amp;nbsp;identifies
itself with a service-unique principal&amp;nbsp;against other services and&amp;nbsp;through
of its own authorization rules it takes the responsibility upon itself that no user
gains illegitimate access to backend data or services. It identifies and takes responsibility
for those that invoke it, but never assumes their identity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The &lt;a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=3a029ead-58f2-405a-a5d1-6cc3513a59fa"&gt;PEACE&lt;/a&gt; tenets
for SO are a composite set. Autonomy is architecturally the most far reaching of the&amp;nbsp;SO
tenets&amp;nbsp;and&amp;nbsp;it is much more&amp;nbsp;about the inside and fundamental behavior
of a service&amp;nbsp;than about its edge.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=69800eae-bf3a-4652-b193-a89e32a900e3" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,69800eae-bf3a-4652-b193-a89e32a900e3.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=d12b4ab8-d615-4c6c-90ed-5e77a830e6ea</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,d12b4ab8-d615-4c6c-90ed-5e77a830e6ea.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,d12b4ab8-d615-4c6c-90ed-5e77a830e6ea.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=d12b4ab8-d615-4c6c-90ed-5e77a830e6ea</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I am back home from San Diego now. About 3 more hours of jet-lag to work on. This
will be a very busy two weeks until I make a little excursion to the <a href="http://www.microsoft.com/middleeast/southgulf/events/pdc/">Pakistan
Developer Conference</a> in Karachi and then have another week to do the final preparations
for <a href="http://www.microsoft.com/europe/teched/">TechEd Europe</a>. 
</p>
        <p>
One of the three realy cool talks I'll do at TechEd Europe is called "Building <em>Proseware</em>"
and explains the the scenario, architecture, and core implementation techniques of <em>Proseware, </em>an
industrial-strength, robust, service-oriented example application that newtelligence has
designed and implemented for Microsoft over the past 2 months. 
</p>
        <p>
The second talk is one that I have been looking forward to for a long
time: Rafal Lukawiecki and myself are going to co-present a session. And if that weren't
enough: The moderator of our little on-stage banter about services is nobody else
than <a href="http://blogs.msdn.com/pathelland">Pat Helland</a>.
</p>
        <p>
And lastly, I'll likely sign-off on the first public version of the <a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=b1d34986-f53b-49c1-a56b-81c5fc042f32">FABRIQ</a> later
this week (we had been waiting for WSE 2.0 to come out), which means that Arvindra
Sehmi and myself can not only repeat our FABRIQ talk in Amsterdam but have shipping
bits to show this time. There will even be a hands-on lab on FABRIQ led by newtelligence
instructors Achim Oellers and Jörg Freiberger. The plan is to launch the bits
before the show, so watch this space for "when and where".
</p>
        <p>
Overall, and as much as I like meeting all my friends in the U.S. and appreciate the
efforts of the TechEd team over there, I think that for the last 4 years TechEd Europe
consistently has been and will be again the better of the two TechEd events from
a developer perspective. In Europe, we have <a href="http://www.microsoft.com/europe/teched/">TechEd</a> and <a href="http://www.microsoft.com/europe/msitforum/">IT
Forum</a>, whereby TechEd is more developer focused and IT Forum is for
the operations side of the house. Hence, TechEd Europe can go and does go a lot deeper into
developer topics than TechEd US. 
</p>
        <p>
There's a lot of work ahead so don't be surprised if the blog falls silent again until
I unleash the information avalanche on Proseware and FABRIQ.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d12b4ab8-d615-4c6c-90ed-5e77a830e6ea" />
      </body>
      <title>And now ... getting ready for TechEd Europe</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,d12b4ab8-d615-4c6c-90ed-5e77a830e6ea.aspx</guid>
      <link>http://vasters.com/clemensv/2004/05/31/And+Now+Getting+Ready+For+TechEd+Europe.aspx</link>
      <pubDate>Mon, 31 May 2004 09:11:16 GMT</pubDate>
      <description>&lt;p&gt;
I am back home from San Diego now. About 3 more hours of jet-lag to work on. This
will be a very busy two weeks until I make a little excursion to the &lt;a href="http://www.microsoft.com/middleeast/southgulf/events/pdc/"&gt;Pakistan
Developer Conference&lt;/a&gt; in Karachi and then have another week to do the final preparations
for &lt;a href="http://www.microsoft.com/europe/teched/"&gt;TechEd Europe&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
One of the&amp;nbsp;three realy cool talks I'll do at TechEd Europe is called&amp;nbsp;"Building &lt;em&gt;Proseware&lt;/em&gt;"
and explains the the scenario, architecture, and core implementation techniques of &lt;em&gt;Proseware, &lt;/em&gt;an
industrial-strength, robust,&amp;nbsp;service-oriented example application that&amp;nbsp;newtelligence&amp;nbsp;has
designed and&amp;nbsp;implemented for Microsoft over the past 2 months. 
&lt;/p&gt;
&lt;p&gt;
The second talk is&amp;nbsp;one that I&amp;nbsp;have been&amp;nbsp;looking forward to for a long
time: Rafal Lukawiecki and myself are going to co-present a session. And if that weren't
enough: The moderator of our little on-stage banter about services is nobody else
than &lt;a href="http://blogs.msdn.com/pathelland"&gt;Pat Helland&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
And lastly, I'll likely sign-off on the first public version of the &lt;a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=b1d34986-f53b-49c1-a56b-81c5fc042f32"&gt;FABRIQ&lt;/a&gt; later
this week (we had been waiting for WSE 2.0 to come out), which means that Arvindra
Sehmi and myself can not only repeat our FABRIQ talk in Amsterdam but have shipping
bits to show this time. There will even be a hands-on lab on FABRIQ led by newtelligence
instructors Achim Oellers and J&amp;#246;rg Freiberger. The plan is to launch the bits
before the show, so watch this space for "when and where".
&lt;/p&gt;
&lt;p&gt;
Overall, and as much as I like meeting all my friends in the U.S. and appreciate the
efforts of the TechEd team over there, I think that for the last 4 years TechEd Europe
consistently has been and will be again the better of the two&amp;nbsp;TechEd events from
a developer perspective. In Europe, we have &lt;a href="http://www.microsoft.com/europe/teched/"&gt;TechEd&lt;/a&gt; and &lt;a href="http://www.microsoft.com/europe/msitforum/"&gt;IT
Forum&lt;/a&gt;,&amp;nbsp;whereby TechEd is&amp;nbsp;more developer focused and IT Forum is for
the operations side of the house. Hence, TechEd Europe can go and does go a lot deeper&amp;nbsp;into
developer topics than TechEd US. 
&lt;/p&gt;
&lt;p&gt;
There's a lot of work ahead so don't be surprised if the blog falls silent again until
I unleash the information avalanche on Proseware and FABRIQ.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d12b4ab8-d615-4c6c-90ed-5e77a830e6ea" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,d12b4ab8-d615-4c6c-90ed-5e77a830e6ea.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
      <category>Talks</category>
      <category>Talks/TechEd Europe</category>
      <category>Talks/TechEd US</category>
      <category>Technology/FABRIQ</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=e33799f0-832f-4006-b498-72dc6feac259</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,e33799f0-832f-4006-b498-72dc6feac259.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,e33799f0-832f-4006-b498-72dc6feac259.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=e33799f0-832f-4006-b498-72dc6feac259</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
All the wonderful loose coupling on the service boundary doesn't help you the least
bit, if you tightly couple a set of services on a common store. The temptation is
just too big that some developer will go and make a database join across the "data
domains" of services and cause a co-location dependency of data and schema dependencies
between services. If you share data stores, you break the autonomy rule and you simply
don't have a service.
</p>
        <p>
Separating out data stores means at least that every service has it's own "tablespace"
or "database" and that in-store joins between those stores are absolutely forbidden.
If you have a service managing customers and a service managing invoices, the invoice
service <strong>must</strong> go through the service front for anything that has to
do with customer data. 
</p>
        <p>
If you want to do reporting across data owned by several services, you must have a
reporting service that pulls the data through service interfaces, consolidates
it and creates the reports from there. 
</p>
        <p>
Will this all be a bit slower than coupling in the store? Sure. It will make your
architecture infinitely more agile, though and allows you to implement a lot of clustering
scalability patterns. In that way, autonomy is not about making everything a
Porsche 911; it's about making the roads wider so that nobody (including the Porsche)
ends up in a traffic jam all the time. It's also about paving roads that
not only let you from A to B in one stretch, but also have something useful
called "exits" that let you get off or on that road at any other place between
those two points. 
</p>
        <p>
If you decide to throw out you own customer service and replace it with a wrapper
around Siebel, your invoice service will never learn about that change. If the invoice
service were reaching over into co-located tables owned by the (former) customer service,
you'd have a lot of work to do to untangle things. You don't need to do that untangling
and all that complication. As an architect you should keep things separate from the
start and make it insanely difficult for developers to break those rules. Having different
databases and, better yet, to scatter them over several machines at least at development
time makes it hard enough to keep the discipline.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e33799f0-832f-4006-b498-72dc6feac259" />
      </body>
      <title>Don't share data stores across services</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,e33799f0-832f-4006-b498-72dc6feac259.aspx</guid>
      <link>http://vasters.com/clemensv/2004/05/26/Dont+Share+Data+Stores+Across+Services.aspx</link>
      <pubDate>Wed, 26 May 2004 16:57:02 GMT</pubDate>
      <description>&lt;p&gt;
All the wonderful loose coupling on the service boundary doesn't help you the least
bit, if you tightly couple a set of services on a common store. The temptation is
just too big that some developer will go and make a database join across the "data
domains" of services and cause a co-location dependency of data and schema dependencies
between services. If you share data stores, you break the autonomy rule and you simply
don't have a service.
&lt;/p&gt;
&lt;p&gt;
Separating out data stores means at least that every service has it's own "tablespace"
or "database" and that in-store joins between those stores are absolutely forbidden.
If you have a service managing customers and a service managing invoices, the invoice
service &lt;strong&gt;must&lt;/strong&gt; go through the service front for anything that has to
do with customer data. 
&lt;/p&gt;
&lt;p&gt;
If you want to do reporting across data owned by several services, you must have a
reporting service&amp;nbsp;that pulls the data through service interfaces, consolidates
it and creates the reports from there. 
&lt;/p&gt;
&lt;p&gt;
Will this all be a bit slower than coupling in the store? Sure. It will make your
architecture infinitely more agile, though and allows you to implement a lot of clustering
scalability patterns. In that way, autonomy is not about&amp;nbsp;making everything a
Porsche 911; it's about making the roads wider so that nobody (including the Porsche)
ends up in a traffic jam all the time.&amp;nbsp;It's also about&amp;nbsp;paving roads that
not only&amp;nbsp;let you from&amp;nbsp;A to&amp;nbsp;B in one stretch, but also&amp;nbsp;have something&amp;nbsp;useful
called "exits"&amp;nbsp;that let you get off or on that road at any other place between
those two points. 
&lt;/p&gt;
&lt;p&gt;
If you decide to throw out you own customer service and replace it with a wrapper
around Siebel, your invoice service will never learn about that change. If the invoice
service were reaching over into co-located tables owned by the (former) customer service,
you'd have a lot of work to do to untangle things. You don't need to do that untangling
and all that complication. As an architect you should keep things separate from the
start and make it insanely difficult for developers to break those rules. Having different
databases and, better yet, to scatter them over several machines at least at development
time makes it hard enough to keep the discipline.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e33799f0-832f-4006-b498-72dc6feac259" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,e33799f0-832f-4006-b498-72dc6feac259.aspx</comments>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=3a029ead-58f2-405a-a5d1-6cc3513a59fa</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,3a029ead-58f2-405a-a5d1-6cc3513a59fa.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,3a029ead-58f2-405a-a5d1-6cc3513a59fa.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=3a029ead-58f2-405a-a5d1-6cc3513a59fa</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The four fundamental transaction principles are nicely grouped into the acronym
"ACID" that's simple to remember, and so I was looking for something that's doing
the same for the SOA tenets and that sort of represents what the service idea
has done to the distributed platform wars: 
</p>
        <ul>
          <li>
            <strong>P</strong>olicy-Based Behavior Negotiation</li>
          <li>
            <strong>E</strong>xplicitness of Boundaries</li>
          <li>
            <strong>A</strong>utonomy</li>
          <li>
            <strong>C</strong>ontract 
<br /><strong>E</strong>xchange</li>
        </ul>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=3a029ead-58f2-405a-a5d1-6cc3513a59fa" />
      </body>
      <title>The SOA tenets == PEACE</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,3a029ead-58f2-405a-a5d1-6cc3513a59fa.aspx</guid>
      <link>http://vasters.com/clemensv/2004/05/19/The+SOA+Tenets+PEACE.aspx</link>
      <pubDate>Wed, 19 May 2004 07:56:50 GMT</pubDate>
      <description>&lt;p&gt;
The four fundamental transaction principles are nicely grouped into&amp;nbsp;the acronym
"ACID"&amp;nbsp;that's simple to remember, and so I was looking for something that's doing
the same for the SOA tenets and that sort of&amp;nbsp;represents what the service idea
has done to the distributed platform wars: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;P&lt;/strong&gt;olicy-Based Behavior Negotiation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E&lt;/strong&gt;xplicitness of Boundaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A&lt;/strong&gt;utonomy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt;ontract 
&lt;br&gt;
&lt;strong&gt;E&lt;/strong&gt;xchange&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=3a029ead-58f2-405a-a5d1-6cc3513a59fa" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,3a029ead-58f2-405a-a5d1-6cc3513a59fa.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=04cfedd9-12d3-4070-ab7c-b52bc67fda2d</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,04cfedd9-12d3-4070-ab7c-b52bc67fda2d.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,04cfedd9-12d3-4070-ab7c-b52bc67fda2d.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=04cfedd9-12d3-4070-ab7c-b52bc67fda2d</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <title>Data Services.</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,04cfedd9-12d3-4070-ab7c-b52bc67fda2d.aspx</guid>
      <link>http://vasters.com/clemensv/2004/05/16/Data+Services.aspx</link>
      <pubDate>Sun, 16 May 2004 11:58:07 GMT</pubDate>
      <description>

&lt;div class=Section1&gt;
&lt;p&gt;
Ralf Westphal &lt;a href="http://weblogs.asp.net/ralfw/archive/2004/05/16/132673.aspx"&gt;responded&lt;/a&gt; to &lt;a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=2892db4d-e9d7-4fd0-ac62-5dc1b68e24f5"&gt;this&lt;/a&gt; and
there are really just two sentences that I&amp;#8217;d like to pick out from Ralf&amp;#8217;s
response because that allows me to go a quite a bit deeper into the data services
idea and might help to further clarify what I understand as a service oriented approach
to data and resource management. Ralf says: &lt;i&gt;There is no necessity to put data access
into a service and deploy it pretty far away from its clients.&lt;/i&gt; &lt;i&gt;Sometimes is
might make sense, sometimes it doesn&amp;#8217;t.&lt;/i&gt; 
&lt;/p&gt;
&lt;p&gt;
I like patterns that eliminate that sort of doubt and which allow one to say &amp;#8220;data
services &lt;i&gt;always&lt;/i&gt; make sense&amp;#8221;.
&lt;/p&gt;
&lt;p&gt;
Co-locating data acquisition and storage with business rules inside a service makes
absolute sense if all accessed data can be assumed to be co-located on the same store
and has similar characteristics with regards to the timely accuracy the data must
have. In all other cases, it&amp;#8217;s very beneficial to move data access into a separate,
autonomous data service and as I&amp;#8217;ll explain here, the design can be made so
flexible that the data service consumer won&amp;#8217;t even notice radical architectural
changes to how data is stored. I will show three quite large scenarios to help illustrating
what I mean: A federated warehouse system, a partitioned customer data storage system
and a master/replica catalog system.
&lt;/p&gt;
&lt;p&gt;
The central question that I want to answer is: Why would you want delegate data acquisition
and storage to dedicated services? The short answer is: Because data doesn&amp;#8217;t
always live in a single place and not all data is alike.
&lt;/p&gt;
&lt;div style='border:none;border-bottom:solid windowtext 1.0pt;padding:0in 0in 1.0pt 0in'&gt;
&lt;p style='border:none;padding:0in'&gt;
Here the long answer:
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;b&gt;The Warehouse &lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img width=104 height=163 src="http://staff.newtelligence.net/clemensv/content/binary/image0021234.png" align=left hspace=12&gt;The
Warehouse Inventory Service (WIS) holds data about all the goods/items that are stored
in warehouse. It&amp;#8217;s a data service in the sense that it manages the records (quantity
in stock, reorder levels, items on back order) for the individual goods, performs
some simplistic accounting-like work to allocate pools of items to orders, but it
doesn&amp;#8217;t really contain any sophisticated business rules. The services implementing
the supply order process and the order fulfillment process for customer orders implement
such business rules &amp;#8211; the warehouse service just keeps data records.
&lt;/p&gt;
&lt;p&gt;
&lt;img width=370 height=251 src="http://staff.newtelligence.net/clemensv/content/binary/image00312.png" align=right hspace=12&gt;The
public interface [&amp;#8220;Explicit Boundary&amp;#8221; SOA tenet] for this service is governed
by one (or a set of) WSDL portType(s), which define(s) a set of actions and message
exchanges that the service implements and understands [&amp;#8220;Shared Contract&amp;#8221;
SOA tenet]. Complementary is a deployment-dependent policy definition for the service,
which describes several assertions about the Security and QoS requirements the service
makes [&amp;#8220;Policy&amp;#8221; SOA tenet]. 
&lt;/p&gt;
&lt;p&gt;
The WIS controls its own, isolated store over which it has exclusive control and the
only way that others can get at the content of that data store is through actions
available on the public interface of the service [&amp;#8220;Autonomy&amp;#8221; SOA tenet].
&lt;/p&gt;
&lt;div style='border:none;border-bottom:solid windowtext 1.0pt;padding:0in 0in 1.0pt 0in'&gt;
&lt;p style='border:none;padding:0in'&gt;
Now let&amp;#8217;s say the company running the system is a bit bigger and has a central
website (of which replicas might be hosted in several locations) and has multiple
warehouses from where items can be delivered. So now, we are putting a total of four
instances of WIS into our data centers at the warehouses in New Jersey, Houston, Atlanta
and Seattle. The services need to live there, because only the people on site can
effectively manage the &amp;#8220;shelf/database relationship&amp;#8221;. So how does that
impact the order fulfillment system that used to talk to the &amp;#8220;simple&amp;#8221;
WIS? It doesn&amp;#8217;t, because we can build a dispatcher service implementing the
very same portType that accepts order information, looks at the order&amp;#8217;s shipping
address and routes the allocation requests to the warehouse closest to the shipping
destination. In fact now, the formerly &amp;#8220;dumb&amp;#8221; WIS can be outfitted with
some more sophisticated rules that allow to split or to shift the allocation of items
to orders across or between warehouses to limit freight cost or ensure the earliest
possible delivery in case the preferred warehouse is out of stock for a certain item.
Still, from the perspective of the service consumer, the WIS implementation is still
just a data service. All that additional complexity is hidden in the underlying &amp;#8220;service
tree&amp;#8221;.
&lt;/p&gt;
&lt;p style='border:none;padding:0in'&gt;
While all the services implement the very same portType, their service policies may
differ significantly. Authentication may require certificates for one warehouse and
some other token for another warehouse. The connection to some warehouses might be
done through a typically rock-solid reliable direct leased line, while another is
reached through a less-than-optimal Internet tunnel, which impacts the application-level
demand for the reliable messaging assurances. All these aspects are deployment specific
and hence made an external deployment-time choice. That&amp;#8217;s why WS-Policy exists.
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;b&gt;The Customer Data Storage&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img width=104 height=163 src="http://staff.newtelligence.net/clemensv/content/binary/image00412.png" align=left hspace=12&gt;This
scenario for the Customer Data Storage Service (CDS) starts as simple as the Warehouse
Inventory scenario and with a single service. The design principles are the same.
&lt;/p&gt;
&lt;p&gt;
Now let&amp;#8217;s assume we&amp;#8217;re running a quite sophisticated e-commerce site where
customers can customize quite a few aspects of the site, can store and reload shopping
carts, make personal annotations on items, and can review &lt;img width=408 height=247 src="http://staff.newtelligence.net/clemensv/content/binary/image0051.png" align=right hspace=12&gt;their
own order history. Let&amp;#8217;s also assume that we&amp;#8217;re pretty aggressively tracking
what they look at, what their search keywords are and also what items they put into
any shopping cart so that we can show them a very personalized selection of goods
that precisely matches their interest profile. Let&amp;#8217;s say that all-in-all, we
need to have storage space of about 2Mbytes for the cumulative profile/tracking data
of each customer. And we happen to have 2 million customers. Even in the Gigabyte
age, ~4mln Mbytes (4TB) is quite a bit of data payload to manage in a read/write access
database that should be reasonably responsive.
&lt;/p&gt;
&lt;p&gt;
So, the solution is to partition the customer data across an array of smaller (cheaper!)
machines that each holds a bucket of customer records. With that we&amp;#8217;re also
eliminating the co-location assumption.
&lt;/p&gt;
&lt;p&gt;
As in the warehouse case, we are putting a dispatcher service implementing the very
same CDS portType on top of the partitioned data service array and therefore hide
the storage strategy re-architecture from the service consumers entirely. With this
application-level partitioning strategy (and a set of auxiliary service to manage
partitions that I am not discussing here), we could scale this up to 2 billion customers
and still have an appropriate architecture. Mind that we can have any number of dispatcher
instances as long as they implement the same rules for how to route requests to partitions.
Strategies for this are a direct partition reference in the customer identifier or
a locator service sitting on &lt;img width=639 height=283 src="http://staff.newtelligence.net/clemensv/content/binary/image0061.png" align=left hspace=12&gt;a
customer/machine lookup dictionary.
&lt;/p&gt;
&lt;p&gt;
Now you might say &amp;#8220;my database engine does this for me&amp;#8221;. Yes, so-called
&amp;#8220;shared-nothing&amp;#8221; clustering techniques do exist on the database level
for a while now, but the following addition to the scenario mandates putting more
logic into the dispatching and allocation service than &amp;#8211; for instance &amp;#8211;
SQL Server&amp;#8217;s &amp;#8220;distributed partitioned views&amp;#8221; are ready to deal with. 
&lt;/p&gt;
&lt;p&gt;
What I am adding to the picture is the &lt;i&gt;European Union&amp;#8217;s &lt;a href="http://europa.eu.int/comm/internal market/privacy/law en.htm"&gt;Data
Privacy Directive&lt;/a&gt;&lt;/i&gt;. Very simplified, the EU directives and regulations it is
illegal to permanently store personal data of EU citizens outside EU territory, unless
the storage operator and the legislation governing the operator complies with the
respective &amp;#8220;Safe Harbor&amp;#8221; regulations spelled out in these EU rules. 
&lt;/p&gt;
&lt;p&gt;
So let&amp;#8217;s say we&amp;#8217;re a tiny little bit evil and want to treat EU data according
to EU rules, but be more &amp;#8220;relaxed&amp;#8221; about data privacy for the rest of
the world. Hence, we permanently store all EU customer data in a data center near
Dublin, Ireland and the data for the rest of the world in a data center in Dallas,
TX (not making any implications here).
&lt;/p&gt;
&lt;p&gt;
In that case, we&amp;#8217;re adding yet another service on top of the unaltered partitioning
architecture that implements the same CDS contract and which internally implements
the appropriate data routing and service access rules. Those rules which will most
likely be based on some location code embedded in the customer identifier (&amp;#8220;&lt;b&gt;E&lt;/b&gt;1223344&amp;#8221;
vs. &amp;#8220;&lt;b&gt;U&lt;/b&gt;1223344&amp;#8221;). Based on these rules, requests are dispatched
to the right data center. To improve performance and avoid having to data travel along
the complete path repeatedly or in small chunks during an interactive session with
the customer (customer is logged into the web site), the dispatcher service might
choose to have a temporary, non-permanent cache for customer data that is filled with
a single request and allows quicker and repeat access to customer data. Changes to
the customer&amp;#8217;s data that result from the interactive session can later be replicated
out to the remote permanent storage. 
&lt;/p&gt;
&lt;div style='border:none;border-bottom:solid windowtext 1.0pt;padding:0in 0in 1.0pt 0in'&gt;
&lt;p style='border:none;padding:0in'&gt;
Again, the service consumer doesn&amp;#8217;t really need to know about these massive
architectural changes in the underlying data services tree. It only talks to a service
that understands a well-known contract.
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;b&gt;The Catalog System&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img width=104 height=163 src="http://staff.newtelligence.net/clemensv/content/binary/image0071.png" align=left hspace=12&gt;Same
picture to boot with and the same rules: Here we have a simple service fronting a
catalog database. If you have millions of catalog items with customer reviews, pictures,
audio and/or video clips, you might chose to partition this just like we did with
the customer data.
&lt;/p&gt;
&lt;p&gt;
If you have different catalogs depending on the markets you are selling into (for
instance German-language books for Austria, Switzerland and Germany), you might want
to partition by location just as in the warehouse scenario.
&lt;/p&gt;
&lt;p&gt;
One thing that&amp;#8217;s very special about catalog data is that very much of it rarely
ever changes. Reviews are added, &lt;img width=482 height=418 src="http://staff.newtelligence.net/clemensv/content/binary/image008.png" align=right hspace=12&gt;media
might be added, but except for corrections, the title, author, ISBN number and content
summary for a book really doesn&amp;#8217;t ever change as long as the book is kept in
the catalog. Such data is essentially &amp;#8220;insert once, change never&amp;#8221;. It&amp;#8217;s
read-only for all practical purposes.
&lt;/p&gt;
&lt;p&gt;
What&amp;#8217;s wonderful about read-only data is that you can replicate it, cache it,
move it close to the consumer and pre-index it. You&amp;#8217;re expecting that a lot
of people will search for items with &amp;#8220;Christmas&amp;#8221; in the item description
come November? Instead of running a full text search every time, run that query once,
save the result set in an extra table and have the stored procedure running the &amp;#8220;QueryByItemDescription&amp;#8221;
activity simply return the entire table if it sees that keyword. Read-only data is
optimization heaven.
&lt;/p&gt;
&lt;p&gt;
Also, for catalog data, timeliness is not a great concern. If a customer review or
a correction isn&amp;#8217;t immediately reflected on the presentation surface, but only
30 minutes or 3 hours after is has been added to the master catalog, it doesn&amp;#8217;t
do any harm as long as the individual adding such information is sufficiently informed
of such a delay. 
&lt;/p&gt;
&lt;p&gt;
So what we can do to with the catalog is to periodically (every few hours or even
just twice a week) consolidate, pre-index and then propagate the master catalog data
to distributed read-only replicas. The data services fronting the replicas will satisfy
all read operations from the local store and will delegate all write operations directly
(passthrough) to the master catalog service. They might choose to update their local
replica to reflect those changes immediately, but that would preclude editorial or
validation rules that might be enforced by the master catalog service. 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
So there you have it. What I&amp;#8217;ve described here is the net effect of sticking
to SOA rules. 
&lt;/p&gt;
&lt;p style='margin-left:.5in;text-indent:-.25in'&gt;
&lt;span style='font-family:Symbol'&gt;&amp;middot;&lt;span style='font:7.0pt "Times New Roman"'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;Shared
Contract:&lt;/b&gt; Any number of services can implement the same contract (although the
concrete implementation, purpose and hence their type differ). Layering contract-compatible
services with gradually increasing levels of abstractions and refining rules over
existing services creates very clear and simple designs that help you scale and distribute
data very well
&lt;/p&gt;
&lt;p style='margin-left:.5in;text-indent:-.25in'&gt;
&lt;span style='font-family:Symbol'&gt;&amp;middot;&lt;span style='font:7.0pt "Times New Roman"'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;Explicit
Boundaries:&lt;/b&gt; Forbidding foreign access or even knowledge about service internals
allows radical changes inside and &amp;#8220;underneath&amp;#8221; services.
&lt;/p&gt;
&lt;p style='margin-left:.5in;text-indent:-.25in'&gt;
&lt;span style='font-family:Symbol'&gt;&amp;middot;&lt;span style='font:7.0pt "Times New Roman"'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;Autonomy&lt;/b&gt; allows
for data partitioning and data access optimization and avoids &amp;#8220;tight coupling
in the backend&amp;#8221;. 
&lt;/p&gt;
&lt;p style='margin-left:.5in;text-indent:-.25in'&gt;
&lt;span style='font-family:Symbol'&gt;&amp;middot;&lt;span style='font:7.0pt "Times New Roman"'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;Policy:&lt;/b&gt; Separating
out policy from the service/message contract allows flexible deployment of the compatible
services across a variety of security and trust scenarios and also allows for dynamic
adaptation to &amp;#8220;far&amp;#8221; or &amp;#8220;near&amp;#8221; communications paths by mandating
certain QoS properties such as reliable messaging.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;&amp;nbsp;&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
Service-Orientation is most useful if you don&amp;#8217;t consider it as just another
technique or tool, but embrace it as a paradigm. And very little of this thinking
has to do with SOAP or XML. SOAP and XML are indeed just tools.
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=04cfedd9-12d3-4070-ab7c-b52bc67fda2d" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,04cfedd9-12d3-4070-ab7c-b52bc67fda2d.aspx</comments>
      <category>Architecture</category>
      <category>Architecture/SOA</category>
    </item>
  </channel>
</rss>