<?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</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=4541fd70-3771-44ae-975f-65c22ba05756</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,4541fd70-3771-44ae-975f-65c22ba05756.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,4541fd70-3771-44ae-975f-65c22ba05756.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=4541fd70-3771-44ae-975f-65c22ba05756</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Over on my new Channel 9 blog I've started a series that will (hopefully) help novices
with getting started developing applications that leverage Windows Azure Service Bus
(and, in coming episodes also Service Bus for Windows Server)
</p>
        <p>
The first two episodes are up:
</p>
        <ul>
          <li>
            <a href="http://channel9.msdn.com/Blogs/Subscribe/Getting-Started-with-Service-Bus-Part-1-The-Portal">Getting
Started with Service Bus. Part 1: The Portal</a>
          </li>
          <li>
            <a href="http://channel9.msdn.com/Blogs/Subscribe/Getting-Started-with-Service-Bus-Part-2-NET-SDK-and-Visual-Studio">Getting
Started with Service Bus. Part 2: .NET SDK and Visual Studio</a> </li>
        </ul>
        <p>
There's much more to come, and the best way to get at it as it comes out is to subscribe
to the <a href="http://channel9.msdn.com/Blogs/Subscribe/RSS">RSS feed</a> or <a href="http://channel9.msdn.com/Blogs/Subscribe">bookmark
the landing page</a>.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=4541fd70-3771-44ae-975f-65c22ba05756" />
      </body>
      <title>Subscribe! - Getting Started with Service Bus</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,4541fd70-3771-44ae-975f-65c22ba05756.aspx</guid>
      <link>http://vasters.com/clemensv/2012/12/05/Subscribe+Getting+Started+With+Service+Bus.aspx</link>
      <pubDate>Wed, 05 Dec 2012 15:12:19 GMT</pubDate>
      <description>&lt;p&gt;
Over on my new Channel 9 blog I've started a series that will (hopefully) help novices
with getting started developing applications that leverage Windows Azure Service Bus
(and, in coming episodes also&amp;nbsp;Service Bus for Windows Server)
&lt;/p&gt;
&lt;p&gt;
The first two episodes are up:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://channel9.msdn.com/Blogs/Subscribe/Getting-Started-with-Service-Bus-Part-1-The-Portal"&gt;Getting
Started with Service Bus. Part 1: The&amp;nbsp;Portal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://channel9.msdn.com/Blogs/Subscribe/Getting-Started-with-Service-Bus-Part-2-NET-SDK-and-Visual-Studio"&gt;Getting
Started with Service Bus. Part 2: .NET SDK and Visual&amp;nbsp;Studio&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
There's much more to come, and the best way to get at it as it comes out is to subscribe
to the &lt;a href="http://channel9.msdn.com/Blogs/Subscribe/RSS"&gt;RSS feed&lt;/a&gt; or &lt;a href="http://channel9.msdn.com/Blogs/Subscribe"&gt;bookmark
the landing page&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=4541fd70-3771-44ae-975f-65c22ba05756" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,4541fd70-3771-44ae-975f-65c22ba05756.aspx</comments>
      <category>Architecture</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=c78e6d0c-dbee-4655-9944-29489df4d6f8</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,c78e6d0c-dbee-4655-9944-29489df4d6f8.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,c78e6d0c-dbee-4655-9944-29489df4d6f8.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=c78e6d0c-dbee-4655-9944-29489df4d6f8</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Here's a short video explaining where I’m at now (<a href="http://binged.it/TfDdKV">here’s
a map</a>) and what I’m up to. Meanwhile I’ve also figured out how to put sound on
both channels with the setup that I have, but here it’s still just on the left channel
and also doesn’t sound as good as it should as I don’t have all the white-noise correcting
Jedi motions mastered.   
</p>
        <p>
Spoiler: I’ll start doing a video show on a regular basis and need input for content
planning, so if you have any ideas, don’t hesitate to <a href="mailto:clemensv@microsoft.com?subject=Video%20Show">send
me email</a> or Tweet me at @clemensv. 
</p>
        <iframe height="315" src="http://www.youtube.com/embed/tS-XwMfGlfc?rel=0" frameborder="0" width="560" allowfullscreen="allowfullscreen">
        </iframe>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=c78e6d0c-dbee-4655-9944-29489df4d6f8" />
      </body>
      <title>Where I&amp;rsquo;m at, what&amp;rsquo;s next, and asking for some help</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,c78e6d0c-dbee-4655-9944-29489df4d6f8.aspx</guid>
      <link>http://vasters.com/clemensv/2012/11/26/Where+Irsquom+At+Whatrsquos+Next+And+Asking+For+Some+Help.aspx</link>
      <pubDate>Mon, 26 Nov 2012 09:06:26 GMT</pubDate>
      <description>&lt;p&gt;
Here's a short video explaining where I’m at now (&lt;a href="http://binged.it/TfDdKV"&gt;here’s
a map&lt;/a&gt;) and what I’m up to. Meanwhile I’ve also figured out how to put sound on
both channels with the setup that I have, but here it’s still just on the left channel
and also doesn’t sound as good as it should as I don’t have all the white-noise correcting
Jedi motions mastered.&amp;nbsp;&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Spoiler: I’ll start doing a video show on a regular basis and need input for content
planning, so if you have any ideas, don’t hesitate to &lt;a href="mailto:clemensv@microsoft.com?subject=Video%20Show"&gt;send
me email&lt;/a&gt; or Tweet me at @clemensv. 
&lt;/p&gt;
&lt;iframe height=315 src="http://www.youtube.com/embed/tS-XwMfGlfc?rel=0" frameborder=0 width=560 allowfullscreen="allowfullscreen"&gt;
&lt;/iframe&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=c78e6d0c-dbee-4655-9944-29489df4d6f8" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,c78e6d0c-dbee-4655-9944-29489df4d6f8.aspx</comments>
      <category>Architecture</category>
      <category>Blog</category>
      <category>Talks</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=abf20c1d-a3f3-4070-b54e-2a922156343a</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,abf20c1d-a3f3-4070-b54e-2a922156343a.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,abf20c1d-a3f3-4070-b54e-2a922156343a.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=abf20c1d-a3f3-4070-b54e-2a922156343a</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I just got off the call with a customer and had a bit of a déjà vu from a meeting
at the beginning of the week, so it looks like the misconception I'll explain here
is a bit more common than I expected. 
</p>
        <p>
In both cases, the folks I talked to, had the about equivalent of the following code
in their app: 
</p>
        <p>
          <span style="FONT-FAMILY: Consolas">var qc = factory.CreateQueueClient(…);<br />
for( int i = 0; i &lt; 1000; i++ ) 
<br />
{<br />
… create message …<br />
qc.BeginSend( msg, null, null );<br />
}<br />
qc.Close(); </span>
        </p>
        <p>
In both cases, the complaint was that messages were lost and strange exceptions occurred
in the logs – which is because, well, this doesn't do what they thought it does. 
</p>
        <p>
          <em>BeginSend</em> in the Service Bus APIs or other networking APIs as much as BeginWrite
on the file system isn't really doing the work that is requested. It is putting a
job into a job queue – the job queue of the I/O thread scheduler. 
</p>
        <p>
That means that once the code reaches <em>qc.Close()</em> and you have also been mighty
lucky, a few messages may indeed have been sent, but the remaining messages will now
still sit in that job queue and scheduled for an object that the code just forced
to close. With the result that every subsequent send operation that is queued but
hasn't been scheduled yet will throw as you're trying to send on a disposed object.
Those messages will fail out and be lost inside the sender's process. 
</p>
        <p>
What's worse is that writing such code stuffs a queue that is both out of the app's
control and out of the app's sight and that all the arguments (which can be pretty
big when we talk about messages) dangle on those jobs filling up memory. Also, since
the app doesn't call <em>EndSend()</em>, the application also doesn't pick up whatever
exceptions are potentially raised by the Send operation and flies completely blind.
If there is an EndXXX method for an async operation, you _must_ call that method even
if it doesn't return any values, because it might quite well throw you back what went
wrong. 
</p>
        <p>
So how should you do it? Don't throw messages blindly into the job queue. It's ok
to queue up a few to make sure there's a job in the queue as another one completes
(which is just slightly trickier than what I want to illustrate here), but generally
you should make subsequent sends depend on previous sends completing. In .NET 4.5
with async/await that's a lot easier now: 
</p>
        <p>
          <span style="FONT-FAMILY: Consolas">var qc = factory.CreateQueueClient(…);<br />
for( int i = 0; i &lt; 1000; i++ ) 
<br />
{<br />
… create message …<br />
await task.Factory.FromAsync(qc.BeginSend, qc.EndSend, msg, null );<br />
}<br />
qc.Close(); </span>
        </p>
        <p>
Keep in mind that the primary goal of async I/O is to not waste threads and lose time
through excessive thread switching as threads hang on I/O operations. <strong><em>It's
not making the I/O magically faster per-se</em></strong>. We achieve that in the above
example as the compiler will break up that code into distinct methods where the loop
continues on an I/O thread callback once the Send operation has completed. 
</p>
        <p>
Summary: 
</p>
        <ol>
          <li>
Don't stuff the I/O scheduler queue with loads of blind calls to BeginXXX without
consideration for how the work gets done and completed and that it can actually fail 
</li>
          <li>
Always call End and think about how many operations you want to have in flight and
what happens to the objects that are attached to the in-flight jobs</li>
        </ol>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=abf20c1d-a3f3-4070-b54e-2a922156343a" />
      </body>
      <title>Service Bus: BeginSend is no magic async pixie dust</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,abf20c1d-a3f3-4070-b54e-2a922156343a.aspx</guid>
      <link>http://vasters.com/clemensv/2012/10/19/Service+Bus+BeginSend+Is+No+Magic+Async+Pixie+Dust.aspx</link>
      <pubDate>Fri, 19 Oct 2012 09:29:10 GMT</pubDate>
      <description>&lt;p&gt;
I just got off the call with a customer and had a bit of a déjà vu from a meeting
at the beginning of the week, so it looks like the misconception I'll explain here
is a bit more common than I expected. 
&lt;/p&gt;
&lt;p&gt;
In both cases, the folks I talked to, had the about equivalent of the following code
in their app: 
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-FAMILY: Consolas"&gt;var qc = factory.CreateQueueClient(…);&lt;br&gt;
for( int i = 0; i &amp;lt; 1000; i++ ) 
&lt;br&gt;
{&lt;br&gt;
… create message …&lt;br&gt;
qc.BeginSend( msg, null, null );&lt;br&gt;
}&lt;br&gt;
qc.Close(); &lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
In both cases, the complaint was that messages were lost and strange exceptions occurred
in the logs – which is because, well, this doesn't do what they thought it does. 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;BeginSend&lt;/em&gt; in the Service Bus APIs or other networking APIs as much as BeginWrite
on the file system isn't really doing the work that is requested. It is putting a
job into a job queue – the job queue of the I/O thread scheduler. 
&lt;/p&gt;
&lt;p&gt;
That means that once the code reaches &lt;em&gt;qc.Close()&lt;/em&gt; and you have also been mighty
lucky, a few messages may indeed have been sent, but the remaining messages will now
still sit in that job queue and scheduled for an object that the code just forced
to close. With the result that every subsequent send operation that is queued but
hasn't been scheduled yet will throw as you're trying to send on a disposed object.
Those messages will fail out and be lost inside the sender's process. 
&lt;/p&gt;
&lt;p&gt;
What's worse is that writing such code stuffs a queue that is both out of the app's
control and out of the app's sight and that all the arguments (which can be pretty
big when we talk about messages) dangle on those jobs filling up memory. Also, since
the app doesn't call &lt;em&gt;EndSend()&lt;/em&gt;, the application also doesn't pick up whatever
exceptions are potentially raised by the Send operation and flies completely blind.
If there is an EndXXX method for an async operation, you _must_ call that method even
if it doesn't return any values, because it might quite well throw you back what went
wrong. 
&lt;/p&gt;
&lt;p&gt;
So how should you do it? Don't throw messages blindly into the job queue. It's ok
to queue up a few to make sure there's a job in the queue as another one completes
(which is just slightly trickier than what I want to illustrate here), but generally
you should make subsequent sends depend on previous sends completing. In .NET 4.5
with async/await that's a lot easier now: 
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-FAMILY: Consolas"&gt;var qc = factory.CreateQueueClient(…);&lt;br&gt;
for( int i = 0; i &amp;lt; 1000; i++ ) 
&lt;br&gt;
{&lt;br&gt;
… create message …&lt;br&gt;
await task.Factory.FromAsync(qc.BeginSend, qc.EndSend, msg, null );&lt;br&gt;
}&lt;br&gt;
qc.Close(); &lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
Keep in mind that the primary goal of async I/O is to not waste threads and lose time
through excessive thread switching as threads hang on I/O operations. &lt;strong&gt;&lt;em&gt;It's
not making the I/O magically faster per-se&lt;/em&gt;&lt;/strong&gt;. We achieve that in the above
example as the compiler will break up that code into distinct methods where the loop
continues on an I/O thread callback once the Send operation has completed. 
&lt;/p&gt;
&lt;p&gt;
Summary: 
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Don't stuff the I/O scheduler queue with loads of blind calls to BeginXXX without
consideration for how the work gets done and completed and that it can actually fail 
&lt;li&gt;
Always call End and think about how many operations you want to have in flight and
what happens to the objects that are attached to the in-flight jobs&lt;/li&gt;
&lt;/ol&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=abf20c1d-a3f3-4070-b54e-2a922156343a" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,abf20c1d-a3f3-4070-b54e-2a922156343a.aspx</comments>
      <category>Architecture</category>
      <category>Technology</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=99035bd6-2110-4b0d-bf9e-e337ee1342a1</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,99035bd6-2110-4b0d-bf9e-e337ee1342a1.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,99035bd6-2110-4b0d-bf9e-e337ee1342a1.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=99035bd6-2110-4b0d-bf9e-e337ee1342a1</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
We get a ton of inquiries along the lines of “I want to program my firewall using
IP ranges to allow outbound access only to my cloud-based apps”. If you (or the IT
department) insist on doing this with Windows Azure, there is even a downloadable
and fairly regularly updated list of the IP ranges <a href="http://www.microsoft.com/en-us/download/details.aspx?id=29840" target="_blank">on
the Microsoft Download Center</a> in a straightforward XML format.
</p>
        <p>
Now, we do know that there are a lot of customers who keep insisting on using IP address
ranges for that purpose, but that strategy is not a recipe for success. 
</p>
        <p>
The IP ranges shift and expand on a very frequent basis and cover all of the Windows
Azure services. Thus, a customer will open their firewall for traffic for the entire
multitenant range of Azure, which means that the customer’s environment can reach
their own apps and the backend services for the “Whack A Panda” game just the same.
With apps in the cloud, there is no actual security gain from these sorts of constraints;
pretty much all the advantages of automated, self-service cloud environments stem
from shared resources including shared networking and shared gateways and the ability
to do dynamic failover including cross-DC failover and the like that means that there
aren’t any reservations at the IP level that last forever.
</p>
        <p>
The best way to handle this is to do the exact inverse of what’s being tried with
these rules, and rather limit access to outside resources to a constrained set of
services based on the services’ or users’ identity as it is done on our Microsoft
corporate network. At Microsoft, you can’t get out through the NAT/Proxy unless you
have an account that has external network privileges. If you are worried about a service
or user abusing access to the Internet, don’t give them Internet. If you think you
need to have tight control, make a DMZ – in the opposite direction of how you usually
think about a DMZ. 
</p>
        <p>
Using IP-address based outbound firewall access rules constraining access to public
cloud computing resources is probably getting a box on a check-list ticked, but it
doesn’t add anything from a security perspective. It’s theater. IMHO.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=99035bd6-2110-4b0d-bf9e-e337ee1342a1" />
      </body>
      <title>"I want to program my firewall using IP ranges to allow outbound access only to my cloud apps"</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,99035bd6-2110-4b0d-bf9e-e337ee1342a1.aspx</guid>
      <link>http://vasters.com/clemensv/2012/07/31/I+Want+To+Program+My+Firewall+Using+IP+Ranges+To+Allow+Outbound+Access+Only+To+My+Cloud+Apps.aspx</link>
      <pubDate>Tue, 31 Jul 2012 17:42:27 GMT</pubDate>
      <description>&lt;p&gt;
We get a ton of inquiries along the lines of “I want to program my firewall using
IP ranges to allow outbound access only to my cloud-based apps”. If you (or the IT
department) insist on doing this with Windows Azure, there is even a downloadable
and fairly regularly updated list of the IP ranges &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=29840" target=_blank&gt;on
the Microsoft Download Center&lt;/a&gt; in a straightforward XML format.
&lt;/p&gt;
&lt;p&gt;
Now, we do know that there are a lot of customers who keep insisting on using IP address
ranges for that purpose, but that strategy is not a recipe for success. 
&lt;/p&gt;
&lt;p&gt;
The IP ranges shift and expand on a very frequent basis and cover all of the Windows
Azure services. Thus, a customer will open their firewall for traffic for the entire
multitenant range of Azure, which means that the customer’s environment can reach
their own apps and the backend services for the “Whack A Panda” game just the same.
With apps in the cloud, there is no actual security gain from these sorts of constraints;
pretty much all the advantages of automated, self-service cloud environments stem
from shared resources including shared networking and shared gateways and the ability
to do dynamic failover including cross-DC failover and the like that means that there
aren’t any reservations at the IP level that last forever.
&lt;/p&gt;
&lt;p&gt;
The best way to handle this is to do the exact inverse of what’s being tried with
these rules, and rather limit access to outside resources to a constrained set of
services based on the services’ or users’ identity as it is done on our Microsoft
corporate network. At Microsoft, you can’t get out through the NAT/Proxy unless you
have an account that has external network privileges. If you are worried about a service
or user abusing access to the Internet, don’t give them Internet. If you think you
need to have tight control, make a DMZ – in the opposite direction of how you usually
think about a DMZ. 
&lt;/p&gt;
&lt;p&gt;
Using IP-address based outbound firewall access rules constraining access to public
cloud computing resources is probably getting a box on a check-list ticked, but it
doesn’t add anything from a security perspective. It’s theater. IMHO.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=99035bd6-2110-4b0d-bf9e-e337ee1342a1" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,99035bd6-2110-4b0d-bf9e-e337ee1342a1.aspx</comments>
      <category>Architecture</category>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=e79915fe-825c-4855-ae7c-0ad01f479238</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,e79915fe-825c-4855-ae7c-0ad01f479238.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,e79915fe-825c-4855-ae7c-0ad01f479238.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=e79915fe-825c-4855-ae7c-0ad01f479238</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I had a email discussion late last weekend and through this weekend on the topic of
transactions in Windows Azure. One of our technical account managers asked me on behalf
of their clients how the client could migrate their solution to Windows Azure without
having to make very significant changes to their error management strategy – a.k.a.
transactions. In the respective solution, the customer has numerous transactions that
are interconnected by queuing and they’re looking for a way to preserve the model
of taking data from a queue or elsewhere, performing an operation on a data store
and writing to a queue as a result as an atomic operation. 
</p>
        <p>
I’ve boiled down the question part of the discussion into single sentences and edited
out the customer specific pieces, but left my answers mostly intact, so this isn’t
written as a blog article.  
</p>
        <p>
The bottom line is that Service Bus, specifically with its de-duplication features
for sending and with its reliable delivery support using Peek-Lock (which we didn’t
discuss in the thread, but see <a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh851750.aspx" target="_blank">here</a> and
also <a href="http://geekswithblogs.net/asmith/archive/2012/04/02/149176.aspx" target="_blank">here</a>)
is a great tool to compensate for the lack of coordinator support in the cloud. I
also discuss why using DTC even in IaaS may not be an ideal choice:
</p>
        <p>
          <strong>Q: How do I perform distributed, coordinated transactions in Windows Azure?</strong>
        </p>
        <p>
2PC in the cloud is hard for <a href="http://blogs.msdn.com/b/clemensv/archive/2011/10/06/achieving-transactional-behavior-with-messaging.aspx">all
sorts of reasons</a>. 2PC as implemented by DTC effectively depends on the coordinator
and its log and connectivity to the coordinator to be very highly available. It also
depends on all parties cooperating on a positive outcome in an expedient fashion.
To that end, you need to <a href="http://msdn.microsoft.com/en-us/library/cc730992(WS.10).aspx">run
DTC in a failover cluster</a>, because it’s the Achilles heel of the whole system
and any transaction depends on DTC clearing it. 
</p>
        <p>
In cloud environments, it’s a very tall order to create a cluster that’s designed
in a way similar to what you can do on-premises by putting a set of machines side-by-side
and interconnecting them redundantly. Even then, use of DTC still put you into a <a href="http://www.julianbrowne.com/article/viewer/brewers-cap-theorem">CAP-like
tradeoff situation</a> as you need to scale up. 
</p>
        <p>
Since the systems will be running in a commoditized environment where the clustered
assets may quite well be subject to occasional network partitions or at least significant
congestion and the system will always require – per 2PC rules – full consensus by
all parties about the transaction outcome, the system will inevitably grind to a halt
whenever there are sporadic network partitions. That risk increases significantly
as the scale of the solution and the number of participating nodes increases. 
</p>
        <p>
There are two routes out of the dilemma. The first is to localize any 2PC work onto
a node and scale up, which lets you stay in the classic model, but will limit the
benefits of using the cloud to having externalized hosting. The second is to give
up on 2PC and use per-resource transaction support (i.e. transactions in SQL or transactions
in Service Bus) as a foundation and knit components together using reliable messaging,
sagas/compensation for error management and, with that, scale out.  
<br /></p>
        <p>
          <strong>Q: Essentially you are saying that there is absolutely no way of building
a coordinator in the cloud?</strong>
        </p>
        <p>
I’m not saying it’s absolutely impossible. I’m saying you’d generally be trading a
lot of what people expect out of cloud (HA, scale) for a classic notion of strong
consistency unless you do a lot of work to support it. 
</p>
        <p>
The Azure storage folks <a href="http://sigops.org/sosp/sosp11/current/2011-Cascais/11-calder-online.pdf">implement
their clusters in a very particular way</a> to provide highly-scalable, highly-available,
and strongly consistent storage – and they are using a quorum based protocol (<a href="http://en.wikipedia.org/wiki/Paxos_algorithm">Paxos</a>)
rather than classic atomic TX protocol to reach consensus. And they do while having
special clusters that are designed specifically to that architecture – because they
are part of the base platform. The paper explains that well. 
</p>
        <p>
Since the storage system and none of the other components trust external parties to
be in control of their internal consistency model and operations – which would be
case if they’d enlist in distributed transactions – any architecture built on top
of those primitives will either have to follow a similar path to what the storage
folks have done, or start making trades. 
</p>
        <p>
You can stick to the classic DTC model with IaaS; but you will have to give up using
the PaaS services that do not support it, and you may face challenges around availability
traded for consistency as your resources get distributed across the datacenter and
fault domains for – ironically – availability. So ultimately you’ll be hosting a classic
workload in IaaS without having the option of controlling the hardware environment
tightly to increase intra-cluster reliability. 
</p>
        <p>
The alternative is to do what the majority of large web properties do and that is
to deal with these constraints and achieve reliability by combining per-resource transactions,
sagas, idempotency, at-least-once messaging, and eventual consistency. 
</p>
        <p>
          <strong>Q: What are the chances that you will build something that will support at
least transactional handoffs between Service Bus the Azure SQL database?</strong>
        </p>
        <p>
We can’t directly couple a SQL DB and Service Bus because SQL, like storage, doesn’t
allow transactions that span databases for the reasons I cited earlier. 
</p>
        <p>
But there is a workaround using Service Bus that gets you very close. If the customer’s
solution DB had a table called “outbox” and the transactions would write messages
into that table (including the destination queue name and the desired message-id),
they can get full ACID around their DB transactions. With storage, you can achieve
a similar model with batched writes into singular partitions. 
</p>
        <p>
We can’t make that “outbox” table, because it needs to be in the solution’s own DB
and inside their schema. A background worker can then poll that table (or get post-processing
handoff from the transaction component) and then replicate the message into SB. 
</p>
        <p>
If SB has duplicate detection turned on, even intermittent send failures or commit
issues on deleting sent messages from the outbox won’t be a problem, so this simple
message transfer doesn’t require 2PC since the message is 100% replicable including
its message-id and thus the send is idempotent towards SB – while sending to SB in
the context of the original transaction wouldn’t have that. 
</p>
        <p>
With that, they can get away without compensation support, but they need to keep the
transactions local to SQL and the “outbox” model gives the necessary escape hatch
to do that. 
</p>
        <p>
          <strong>Q: How does that work with the duplicate detection?</strong>
        </p>
        <p>
The message-id is a free-form string that the app can decide on and set as it likes.
So that can be an order-id, some contextual transaction identifier or just a Guid.
That id needs to go into the outbox as the message is written. 
</p>
        <p>
If the duplicate detection in Service Bus is turned on for the particular Queue, we
will route the first message and drop any subsequent message with the same message-id
during the duplicate detection time window. The respective message(s) is/are swallowed
by Service Bus and we don’t specifically report that fact. 
</p>
        <p>
With that, you can make the transfer sufficiently robust. 
</p>
        <p>
Duplicate Detection Sample: <a href="http://code.msdn.microsoft.com/windowsazure/Brokered-Messaging-c0acea25#content">http://code.msdn.microsoft.com/windowsazure/Brokered-Messaging-c0acea25#content</a></p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e79915fe-825c-4855-ae7c-0ad01f479238" />
      </body>
      <title>Transactions in Windows Azure (with Service Bus) &amp;ndash; An Email Discussion</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,e79915fe-825c-4855-ae7c-0ad01f479238.aspx</guid>
      <link>http://vasters.com/clemensv/2012/07/30/Transactions+In+Windows+Azure+With+Service+Bus+Ndash+An+Email+Discussion.aspx</link>
      <pubDate>Mon, 30 Jul 2012 18:23:16 GMT</pubDate>
      <description>&lt;p&gt;
I had a email discussion late last weekend and through this weekend on the topic of
transactions in Windows Azure. One of our technical account managers asked me on behalf
of their clients how the client could migrate their solution to Windows Azure without
having to make very significant changes to their error management strategy – a.k.a.
transactions. In the respective solution, the customer has numerous transactions that
are interconnected by queuing and they’re looking for a way to preserve the model
of taking data from a queue or elsewhere, performing an operation on a data store
and writing to a queue as a result as an atomic operation. 
&lt;/p&gt;
&lt;p&gt;
I’ve boiled down the question part of the discussion into single sentences and edited
out the customer specific pieces, but left my answers mostly intact, so this isn’t
written as a blog article.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
The bottom line is that Service Bus, specifically with its de-duplication features
for sending and with its reliable delivery support using Peek-Lock (which we didn’t
discuss in the thread, but see &lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh851750.aspx" target=_blank&gt;here&lt;/a&gt; and
also &lt;a href="http://geekswithblogs.net/asmith/archive/2012/04/02/149176.aspx" target=_blank&gt;here&lt;/a&gt;)
is a great tool to compensate for the lack of coordinator support in the cloud. I
also discuss why using DTC even in IaaS may not be an ideal choice:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Q: How do I perform distributed, coordinated transactions in Windows Azure?&lt;/strong&gt; 
&lt;p&gt;
2PC in the cloud is hard for &lt;a href="http://blogs.msdn.com/b/clemensv/archive/2011/10/06/achieving-transactional-behavior-with-messaging.aspx"&gt;all
sorts of reasons&lt;/a&gt;. 2PC as implemented by DTC effectively depends on the coordinator
and its log and connectivity to the coordinator to be very highly available. It also
depends on all parties cooperating on a positive outcome in an expedient fashion.
To that end, you need to &lt;a href="http://msdn.microsoft.com/en-us/library/cc730992(WS.10).aspx"&gt;run
DTC in a failover cluster&lt;/a&gt;, because it’s the Achilles heel of the whole system
and any transaction depends on DTC clearing it. 
&lt;p&gt;
In cloud environments, it’s a very tall order to create a cluster that’s designed
in a way similar to what you can do on-premises by putting a set of machines side-by-side
and interconnecting them redundantly. Even then, use of DTC still put you into a &lt;a href="http://www.julianbrowne.com/article/viewer/brewers-cap-theorem"&gt;CAP-like
tradeoff situation&lt;/a&gt; as you need to scale up. 
&lt;p&gt;
Since the systems will be running in a commoditized environment where the clustered
assets may quite well be subject to occasional network partitions or at least significant
congestion and the system will always require – per 2PC rules – full consensus by
all parties about the transaction outcome, the system will inevitably grind to a halt
whenever there are sporadic network partitions. That risk increases significantly
as the scale of the solution and the number of participating nodes increases. 
&lt;p&gt;
There are two routes out of the dilemma. The first is to localize any 2PC work onto
a node and scale up, which lets you stay in the classic model, but will limit the
benefits of using the cloud to having externalized hosting. The second is to give
up on 2PC and use per-resource transaction support (i.e. transactions in SQL or transactions
in Service Bus) as a foundation and knit components together using reliable messaging,
sagas/compensation for error management and, with that, scale out.&amp;nbsp; 
&lt;br&gt;
&lt;p&gt;
&lt;strong&gt;Q: Essentially you are saying that there is absolutely no way of building
a coordinator in the cloud?&lt;/strong&gt; 
&lt;p&gt;
I’m not saying it’s absolutely impossible. I’m saying you’d generally be trading a
lot of what people expect out of cloud (HA, scale) for a classic notion of strong
consistency unless you do a lot of work to support it. 
&lt;p&gt;
The Azure storage folks &lt;a href="http://sigops.org/sosp/sosp11/current/2011-Cascais/11-calder-online.pdf"&gt;implement
their clusters in a very particular way&lt;/a&gt; to provide highly-scalable, highly-available,
and strongly consistent storage – and they are using a quorum based protocol (&lt;a href="http://en.wikipedia.org/wiki/Paxos_algorithm"&gt;Paxos&lt;/a&gt;)
rather than classic atomic TX protocol to reach consensus. And they do while having
special clusters that are designed specifically to that architecture – because they
are part of the base platform. The paper explains that well. 
&lt;p&gt;
Since the storage system and none of the other components trust external parties to
be in control of their internal consistency model and operations – which would be
case if they’d enlist in distributed transactions – any architecture built on top
of those primitives will either have to follow a similar path to what the storage
folks have done, or start making trades. 
&lt;p&gt;
You can stick to the classic DTC model with IaaS; but you will have to give up using
the PaaS services that do not support it, and you may face challenges around availability
traded for consistency as your resources get distributed across the datacenter and
fault domains for – ironically – availability. So ultimately you’ll be hosting a classic
workload in IaaS without having the option of controlling the hardware environment
tightly to increase intra-cluster reliability. 
&lt;p&gt;
The alternative is to do what the majority of large web properties do and that is
to deal with these constraints and achieve reliability by combining per-resource transactions,
sagas, idempotency, at-least-once messaging, and eventual consistency. 
&lt;p&gt;
&lt;strong&gt;Q: What are the chances that you will build something that will support at
least transactional handoffs between Service Bus the Azure SQL database?&lt;/strong&gt; 
&lt;p&gt;
We can’t directly couple a SQL DB and Service Bus because SQL, like storage, doesn’t
allow transactions that span databases for the reasons I cited earlier. 
&lt;p&gt;
But there is a workaround using Service Bus that gets you very close. If the customer’s
solution DB had a table called “outbox” and the transactions would write messages
into that table (including the destination queue name and the desired message-id),
they can get full ACID around their DB transactions. With storage, you can achieve
a similar model with batched writes into singular partitions. 
&lt;p&gt;
We can’t make that “outbox” table, because it needs to be in the solution’s own DB
and inside their schema. A background worker can then poll that table (or get post-processing
handoff from the transaction component) and then replicate the message into SB. 
&lt;p&gt;
If SB has duplicate detection turned on, even intermittent send failures or commit
issues on deleting sent messages from the outbox won’t be a problem, so this simple
message transfer doesn’t require 2PC since the message is 100% replicable including
its message-id and thus the send is idempotent towards SB – while sending to SB in
the context of the original transaction wouldn’t have that. 
&lt;p&gt;
With that, they can get away without compensation support, but they need to keep the
transactions local to SQL and the “outbox” model gives the necessary escape hatch
to do that. 
&lt;p&gt;
&lt;strong&gt;Q: How does that work with the duplicate detection?&lt;/strong&gt; 
&lt;p&gt;
The message-id is a free-form string that the app can decide on and set as it likes.
So that can be an order-id, some contextual transaction identifier or just a Guid.
That id needs to go into the outbox as the message is written. 
&lt;p&gt;
If the duplicate detection in Service Bus is turned on for the particular Queue, we
will route the first message and drop any subsequent message with the same message-id
during the duplicate detection time window. The respective message(s) is/are swallowed
by Service Bus and we don’t specifically report that fact. 
&lt;p&gt;
With that, you can make the transfer sufficiently robust. 
&lt;p&gt;
Duplicate Detection Sample: &lt;a href="http://code.msdn.microsoft.com/windowsazure/Brokered-Messaging-c0acea25#content"&gt;http://code.msdn.microsoft.com/windowsazure/Brokered-Messaging-c0acea25#content&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e79915fe-825c-4855-ae7c-0ad01f479238" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,e79915fe-825c-4855-ae7c-0ad01f479238.aspx</comments>
      <category>Architecture</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=77fcaf77-edf6-44b6-b0e7-ff9325dc137d</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,77fcaf77-edf6-44b6-b0e7-ff9325dc137d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,77fcaf77-edf6-44b6-b0e7-ff9325dc137d.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=77fcaf77-edf6-44b6-b0e7-ff9325dc137d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
There’s a lot of talk about “Push” notifications both in web and mobile scenarios.
“Push” is often positioned as something entirely different to “Pull” (or polling).
The reality is that “Push” in the sense that it is used with Web Sockets or Apple/Windows/Android
Push Notification systems is just a pattern nuance away from “Pull”.  
</p>
        <p>
When I discuss that general realm with folks here, I use three terms. “Push”, “Solicited
Push”, and “Pull”. When people talk about “Push” as an explicit thing today, they
usually refer to “Solicited Push”. 
</p>
        <p>
“Solicited Push” and “Pull” are similar in that a message sink (client) receives messages
after having established a connection to a message source. The only difference between
them is how many messages are being asked for by the message sink – and, if you want
to find a second one, whether the message sink will wait for messages to become available
or instantly respond with a negative reply.  The clearly distinct third pattern
is plain “Push” where a message source sends messages to message sinks on connections
that the source initiates. 
</p>
        <ul>
          <li>
“Push” – a message source initiates a connection (or a datagram route) to a message
sink (which has previously indicated the desire to be notified by other means) and
sends a message. This requires that the message sink has independent and reachable
network connectivity from the perspective of the message source. 
</li>
          <li>
“Solicited Push” – a message sink initiates  a connection (or a datagram route)
to a message source and asks for an unbounded sequence of messages. As messages become
available, they are routed via the connection/route. The connection is maintained
for indeterminate time and reestablished once found to be broken for whatever reason. 
</li>
          <li>
“Pull” – message sink initiates a connection (or datagram route) to a message source
and asks for a bounded sequence of messages (1 to N). For “Short Pull”, the message
source immediately completes the operation providing a negative result or a sequence
of less than N messages, for a “Long Pull” the source will keep the request pending
until N messages have become available and routed to the sink. As the overall timeout
for the request is reached or N messages have been retrieved, the message source completes
the operation.</li>
        </ul>
        <p>
Bottom line: “Pull” or short/long polling and “Solicited Push” are just variations
of the same thing. The message sink (client) provides a connection onto which the
message source routes messages that the sink asks for. With “Solicited Push” it’s
an unbounded sequence, with “Pull” is a bounded sequence. 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=77fcaf77-edf6-44b6-b0e7-ff9325dc137d" />
      </body>
      <title>&amp;ldquo;Push&amp;rdquo;</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,77fcaf77-edf6-44b6-b0e7-ff9325dc137d.aspx</guid>
      <link>http://vasters.com/clemensv/2012/07/26/ldquoPushrdquo.aspx</link>
      <pubDate>Thu, 26 Jul 2012 18:25:36 GMT</pubDate>
      <description>&lt;p&gt;
There’s a lot of talk about “Push” notifications both in web and mobile scenarios.
“Push” is often positioned as something entirely different to “Pull” (or polling).
The reality is that “Push” in the sense that it is used with Web Sockets or Apple/Windows/Android
Push Notification systems is just a pattern nuance away from “Pull”.&amp;nbsp; 
&lt;p&gt;
When I discuss that general realm with folks here, I use three terms. “Push”, “Solicited
Push”, and “Pull”. When people talk about “Push” as an explicit thing today, they
usually refer to “Solicited Push”. 
&lt;p&gt;
“Solicited Push” and “Pull” are similar in that a message sink (client) receives messages
after having established a connection to a message source. The only difference between
them is how many messages are being asked for by the message sink – and, if you want
to find a second one, whether the message sink will wait for messages to become available
or instantly respond with a negative reply.&amp;nbsp; The clearly distinct third pattern
is plain “Push” where a message source sends messages to message sinks on connections
that the source initiates. 
&lt;ul&gt;
&lt;li&gt;
“Push” – a message source initiates a connection (or a datagram route) to a message
sink (which has previously indicated the desire to be notified by other means) and
sends a message. This requires that the message sink has independent and reachable
network connectivity from the perspective of the message source. 
&lt;li&gt;
“Solicited Push” – a message sink initiates&amp;nbsp; a connection (or a datagram route)
to a message source and asks for an unbounded sequence of messages. As messages become
available, they are routed via the connection/route. The connection is maintained
for indeterminate time and reestablished once found to be broken for whatever reason. 
&lt;li&gt;
“Pull” – message sink initiates a connection (or datagram route) to a message source
and asks for a bounded sequence of messages (1 to N). For “Short Pull”, the message
source immediately completes the operation providing a negative result or a sequence
of less than N messages, for a “Long Pull” the source will keep the request pending
until N messages have become available and routed to the sink. As the overall timeout
for the request is reached or N messages have been retrieved, the message source completes
the operation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Bottom line: “Pull” or short/long polling and “Solicited Push” are just variations
of the same thing. The message sink (client) provides a connection onto which the
message source routes messages that the sink asks for. With “Solicited Push” it’s
an unbounded sequence, with “Pull” is a bounded sequence. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=77fcaf77-edf6-44b6-b0e7-ff9325dc137d" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,77fcaf77-edf6-44b6-b0e7-ff9325dc137d.aspx</comments>
      <category>Architecture</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=dbe57313-890a-4f19-89ab-5b1738af40a1</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,dbe57313-890a-4f19-89ab-5b1738af40a1.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,dbe57313-890a-4f19-89ab-5b1738af40a1.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=dbe57313-890a-4f19-89ab-5b1738af40a1</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I actually had to double-check whether it’s really true given all my talks and places
where I’ve published articles, but the June 2012 issue of MSDN Magazine is indeed
the first of this storied publication in which I have an article. It’s about the “Internet
of Things” and an exemplary architecture for how to manage flow from and to large
numbers of devices using Service Bus – and the article signals the beginning of an
increasingly deeper SB engagement in that space, so I expect things to get significantly
easier and supported with better abstractions in the future. The July 2012 issue
of MSDN Magazine will feature a follow-up article – with code – that shows how to
implement the key parts of this architecture using an actual .NET Micro Framework
powered device and an Azure application via the Service Bus.
</p>
        <p>
And now <a href="http://msdn.microsoft.com/en-us/magazine/jj133819.aspx" target="_blank">go
here to read the article over on the MSDN Magazine site</a>.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=dbe57313-890a-4f19-89ab-5b1738af40a1" />
      </body>
      <title>MSDN Magazine June 2012: Using Windows Azure Service Bus for &amp;hellip; Things!</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,dbe57313-890a-4f19-89ab-5b1738af40a1.aspx</guid>
      <link>http://vasters.com/clemensv/2012/06/01/MSDN+Magazine+June+2012+Using+Windows+Azure+Service+Bus+For+Hellip+Things.aspx</link>
      <pubDate>Fri, 01 Jun 2012 17:38:31 GMT</pubDate>
      <description>&lt;p&gt;
I actually had to double-check whether it’s really true given all my talks and places
where I’ve published articles, but the June 2012 issue of MSDN Magazine is indeed
the first of this storied publication in which I have an article. It’s about the “Internet
of Things” and an exemplary architecture for how to manage flow from and to large
numbers of devices using Service Bus – and the article signals the beginning of an
increasingly deeper SB engagement in that space, so I expect things to get significantly
easier&amp;nbsp;and supported with better abstractions in the future. The July 2012 issue
of MSDN Magazine will feature a follow-up article – with code – that shows how to
implement the key parts of this architecture using an actual .NET Micro Framework
powered device and an Azure application via the Service Bus.
&lt;/p&gt;
&lt;p&gt;
And now &lt;a href="http://msdn.microsoft.com/en-us/magazine/jj133819.aspx" target=_blank&gt;go
here to read the article over on the MSDN Magazine site&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=dbe57313-890a-4f19-89ab-5b1738af40a1" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,dbe57313-890a-4f19-89ab-5b1738af40a1.aspx</comments>
      <category>Architecture</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I’m toying around with very small and very constrained embedded devices right now.
When you make millions of a small thing, every byte in code footprint and any processing
cycle you can save saves real money. An XML parser is a big chunk of code. So is a
JSON parser. Every HTTP stack already has a key/value pair parser for headers. We
can use that.
</p>
        <p>
NHTTP stands for NoHyperText Transfer Protocol. Yes, I made that up. No, this is not
an April Fool’s joke. Hear me out.
</p>
        <p>
All rules of RFC2616 apply, except for <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2" target="_blank">section
7.2</a>, meaning there is must never an entity body on any request or reply. Instead
we rely entirely on <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.1" target="_blank">section
7.1</a> and its extensibility rule: 
</p>
        <ul>
          <li>
            <em>The extension-header mechanism allows additional entity-header fields to be defined
without changing the protocol, but these fields cannot be assumed to be recognizable
by the recipient. Unrecognized header fields SHOULD be ignored by the recipient and <font color="#ff0000">MUST</font> be
forwarded by transparent proxies.</em>
          </li>
        </ul>
        <p>
All property payloads are expressed as key/value pairs that are directly mapped onto
HTTP headers. No value can exceed 2KB in size and you can’t have more than 32 values
per message so that we stay comfortably within common HTTP infrastructure quotas.
To avoid collisions with existing headers and to allow for easy enumeration, each
property key is prefixed with “P-“ 
</p>
        <p>
POST /foo HTTP/1.1 
<br />
Host: example.com 
<br />
Content-Length: 0 
<br />
P-Name: “Clemens”
</p>
        <p>
HTTP/1.1 200 OK 
<br />
Content-Length: 0 
<br />
P-Greeting: “Hello, Clemens”
</p>
        <p>
(The fun bit is that the Windows Azure Service Bus HTTP API for sending and receiving
messages already supports this exact model since we map custom message properties
to headers and the HTTP entity body to the body of broker messages and those can be
empty)
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb" />
      </body>
      <title>NHTTP</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb.aspx</guid>
      <link>http://vasters.com/clemensv/2012/05/04/NHTTP.aspx</link>
      <pubDate>Fri, 04 May 2012 15:15:33 GMT</pubDate>
      <description>&lt;p&gt;
I’m toying around with very small and very constrained embedded devices right now.
When you make millions of a small thing, every byte in code footprint and any processing
cycle you can save saves real money. An XML parser is a big chunk of code. So is a
JSON parser. Every HTTP stack already has a key/value pair parser for headers. We
can use that.
&lt;/p&gt;
&lt;p&gt;
NHTTP stands for NoHyperText Transfer Protocol. Yes, I made that up. No, this is not
an April Fool’s joke. Hear me out.
&lt;/p&gt;
&lt;p&gt;
All rules of RFC2616 apply, except for &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2" target=_blank&gt;section
7.2&lt;/a&gt;, meaning there is must never an entity body on any request or reply. Instead
we rely entirely on &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.1" target=_blank&gt;section
7.1&lt;/a&gt; and its extensibility rule: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;The extension-header mechanism allows additional entity-header fields to be defined
without changing the protocol, but these fields cannot be assumed to be recognizable
by the recipient. Unrecognized header fields SHOULD be ignored by the recipient and &lt;font color=#ff0000&gt;MUST&lt;/font&gt; be
forwarded by transparent proxies.&lt;/em&gt; 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
All property payloads are expressed as key/value pairs that are directly mapped onto
HTTP headers. No value can exceed 2KB in size and you can’t have more than 32 values
per message so that we stay comfortably within common HTTP infrastructure quotas.
To avoid collisions with existing headers and to allow for easy enumeration, each
property key is prefixed with “P-“ 
&lt;/p&gt;
&lt;p&gt;
POST /foo HTTP/1.1 
&lt;br&gt;
Host: example.com 
&lt;br&gt;
Content-Length: 0 
&lt;br&gt;
P-Name: “Clemens”
&lt;/p&gt;
&lt;p&gt;
HTTP/1.1 200 OK 
&lt;br&gt;
Content-Length: 0 
&lt;br&gt;
P-Greeting: “Hello, Clemens”
&lt;/p&gt;
&lt;p&gt;
(The fun bit is that the Windows Azure Service Bus HTTP API for sending and receiving
messages already supports this exact model since we map custom message properties
to headers and the HTTP entity body to the body of broker messages and those can be
empty)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,8a3fd52b-447c-4a1d-a226-6e01dcf9e3bb.aspx</comments>
      <category>Architecture</category>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=2b9cf892-44e3-4a6c-a254-310402bae5d9</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,2b9cf892-44e3-4a6c-a254-310402bae5d9.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,2b9cf892-44e3-4a6c-a254-310402bae5d9.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=2b9cf892-44e3-4a6c-a254-310402bae5d9</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I just wrote this email on a private mailing list and thought it may make sense to
share it. The context of the discussion was overuse of the term “REST” in a document
discussing an HTTP API:
</p>
        <hr />
        <p>
REST is a set of architectural principles. REST describes how state flows and describes
the shape of relationships between the parties in a distributed system. HTTP is a
protocol with a variety of stacks supporting it, and the REST principles were born
out of developing HTTP. There could, in theory, a broad variety of protocols that
also embody REST architecture, but  there are, in fact, very few (if any) that
aren’t just variations of HTTP. 
</p>
        <p>
“The client sends …”, “The server receives …”, “The server provides an interface for
…” are all statements about implementation and, thus, HTTP. It commonly starts making
talking about REST specifically when debating whether a system is actually following
the principles according to the 5.3.3 “Data View” section in [1], since everything
up to that point in Fielding’s dissertation you get generally for free with HTTP.  
</p>
        <p>
[1] <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm</a></p>
        <p>
          <hr />
        </p>
        <p>
        </p>
        <p>
Bottom line: HTTP APIs are HTTP APIs. REST is about how things hang together. The
terms aren’t interchangeable. In most technical discussions about interfaces or methods
or URIs and most other implementation details, HTTP API is the right term.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=2b9cf892-44e3-4a6c-a254-310402bae5d9" />
      </body>
      <title>&amp;ldquo;REST API&amp;rdquo; or &amp;ldquo;HTTP API&amp;rdquo;?</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,2b9cf892-44e3-4a6c-a254-310402bae5d9.aspx</guid>
      <link>http://vasters.com/clemensv/2012/04/13/ldquoREST+APIrdquo+Or+LdquoHTTP+APIrdquo.aspx</link>
      <pubDate>Fri, 13 Apr 2012 17:25:29 GMT</pubDate>
      <description>&lt;p&gt;
I just wrote this email on a private mailing list and thought it may make sense to
share it. The context of the discussion was overuse of the term “REST” in a document
discussing an HTTP API:
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
REST is a set of architectural principles. REST describes how state flows and describes
the shape of relationships between the parties in a distributed system. HTTP is a
protocol with a variety of stacks supporting it, and the REST principles were born
out of developing HTTP. There could, in theory, a broad variety of protocols that
also embody REST architecture, but&amp;nbsp; there are, in fact, very few (if any) that
aren’t just variations of HTTP. 
&lt;/p&gt;
&lt;p&gt;
“The client sends …”, “The server receives …”, “The server provides an interface for
…” are all statements about implementation and, thus, HTTP. It commonly starts making
talking about REST specifically when debating whether a system is actually following
the principles according to the 5.3.3 “Data View” section in [1], since everything
up to that point in Fielding’s dissertation you get generally for free with HTTP.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
[1] &lt;a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm"&gt;http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Bottom line: HTTP APIs are HTTP APIs. REST is about how things hang together. The
terms aren’t interchangeable. In most technical discussions about interfaces or methods
or URIs and most other implementation details, HTTP API is the right term.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=2b9cf892-44e3-4a6c-a254-310402bae5d9" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,2b9cf892-44e3-4a6c-a254-310402bae5d9.aspx</comments>
      <category>Architecture</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=7bf6ac44-afba-42be-b7ea-3fe298310884</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,7bf6ac44-afba-42be-b7ea-3fe298310884.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,7bf6ac44-afba-42be-b7ea-3fe298310884.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=7bf6ac44-afba-42be-b7ea-3fe298310884</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've long wanted to write an architecture book. The problem with books is that writing
them robs you of at least half a year of your life, and that half a year is a
very painful one. I've done it. So instead of a book, I talked to the folks at Pluralsight
and made an on-demand video course.  
</p>
        <blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
          <p>
            <a href="http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=eda">
              <em>"The
Elements of Distributed Architecture"</em>
            </a>
            <em> is about the foundational
elements of distributed architecture and about the ‘physics’ that affect distributed
software designs. The goal of this course, which is designed to be independent of
specific languages, technologies, and products, is to provide software teams with
a shared baseline of concepts and terminologies in the areas of information management,
communication, presentation, processing, failure management, security, and safety.</em>
          </p>
        </blockquote>
        <p dir="ltr">
I think of this course as a baseline and there's plenty of runway for more
in-depth material. If you like this one that will give me motivation to spend more
private time (this course is not related to my Microsoft job) to create architectural
material.  
</p>
        <p dir="ltr">
If you don't have a Pluralsight account, <a href="https://www.pluralsight-training.net/microsoft/Subscribe/Step1?isTrial=True">you
can sign up for the free trial here</a></p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=7bf6ac44-afba-42be-b7ea-3fe298310884" />
      </body>
      <title>The Elements of Distributed Architecture</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,7bf6ac44-afba-42be-b7ea-3fe298310884.aspx</guid>
      <link>http://vasters.com/clemensv/2011/12/20/The+Elements+Of+Distributed+Architecture.aspx</link>
      <pubDate>Tue, 20 Dec 2011 22:36:22 GMT</pubDate>
      <description>&lt;p&gt;
I've long wanted to write an architecture book. The problem with books is that writing
them&amp;nbsp;robs you of at least half a year of your life, and that half a year is a
very painful one. I've done it. So instead of a book, I talked to the folks at Pluralsight
and made an on-demand video course.&amp;nbsp;&amp;nbsp;
&lt;/p&gt;
&lt;blockquote style="MARGIN-RIGHT: 0px" dir=ltr&gt; 
&lt;p&gt;
&lt;a href="http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=eda"&gt;&lt;em&gt;"The
Elements of Distributed Architecture"&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&amp;nbsp;is about the foundational
elements of distributed architecture and about the ‘physics’ that affect distributed
software designs. The goal of this course, which is designed to be independent of
specific languages, technologies, and products, is to provide software teams with
a shared baseline of concepts and terminologies in the areas of information management,
communication, presentation, processing, failure management, security, and safety.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
I think of this course as a&amp;nbsp;baseline and&amp;nbsp;there's plenty of runway for more
in-depth material. If you like this one that will give me motivation to spend more
private time (this course is not related to my Microsoft job) to create architectural
material.&amp;nbsp;&amp;nbsp;
&lt;/p&gt;
&lt;p dir=ltr&gt;
If you don't have a Pluralsight account,&amp;nbsp;&lt;a href="https://www.pluralsight-training.net/microsoft/Subscribe/Step1?isTrial=True"&gt;you
can sign up for the free trial here&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=7bf6ac44-afba-42be-b7ea-3fe298310884" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,7bf6ac44-afba-42be-b7ea-3fe298310884.aspx</comments>
      <category>Architecture</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=bb1fc000-b441-445b-8909-104bd754f60d</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,bb1fc000-b441-445b-8909-104bd754f60d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,bb1fc000-b441-445b-8909-104bd754f60d.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=bb1fc000-b441-445b-8909-104bd754f60d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Load Balancing on the Service Bus Relay is by far our #1 most requested feature now
that we’ve got Queues and Topics finally in production. It’s reasonable expectation
for us deliver that capability in one of the next production updates and the good
news is that we will. I’m not going to promise any concrete ship dates here, but it’d
be sorely disappointing if that wouldn’t happen while the calendar still says 2011. 
</p>
        <p>
I just completed writing the functional spec for the feature and it’s worth communicating
how the feature will show up, since there is a tiny chance that the behavioral change
may affect implementations that rely on a particular exception to drive the strategy
of how to perform failover. 
</p>
        <p>
The gist of the Load Balancing spec is that the required changes in your code and
config to get load balancing are zero. With either the NetTcpRelayBinding or any of
the HTTP bindings (WebHttpRelayBinding, etc) as well as the underlying transport binding
elements, you’ll just open up a second (and third and fourth … up to 25) listener
on the same name and instead of getting an AddressAlreadyInUseException as you get
today, you’ll just get automatic load balancing. When a request for your endpoints
shows up at Service Bus, the system will roll the dice on which of the connected listeners
to route the request or connection/session to and perform the necessary handshake
to make that happen.
</p>
        <p>
The bottom line is that we’re effectively making the AddressAlreadyInUseException
go away for the most part. It’ll still be thrown when the listener’s policy settings
don’t match up, i.e. when one listener wants to have Access Control enabled and the
other one doesn’t, but otherwise you’ll just won’t see it anymore. 
</p>
        <p>
The only way this way of just lighting up the feature may get anyone in trouble is
if your application were to rely on that exception in a situation where you’ve got
an active listener on Service Bus on one node and a ‘standby’ listener on another
node that keeps trying to open up a listener into the same address to create a hot/warm
cluster failover scheme <em>and</em> if the two nodes were tripping over each other
if they were getting traffic concurrently. That doesn’t seem too likely. If you have
questions about this drop me a line here in the comments, by email to clemensv at
microsoft.com or on Twitter @clemensv.  
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=bb1fc000-b441-445b-8909-104bd754f60d" />
      </body>
      <title>Service Bus Relay Load Balancing&amp;ndash;The Missing Feature (But Not For Much Longer!)</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,bb1fc000-b441-445b-8909-104bd754f60d.aspx</guid>
      <link>http://vasters.com/clemensv/2011/09/20/Service+Bus+Relay+Load+BalancingndashThe+Missing+Feature+But+Not+For+Much+Longer.aspx</link>
      <pubDate>Tue, 20 Sep 2011 23:54:10 GMT</pubDate>
      <description>&lt;p&gt;
Load Balancing on the Service Bus Relay is by far our #1 most requested feature now
that we’ve got Queues and Topics finally in production. It’s reasonable expectation
for us deliver that capability in one of the next production updates and the good
news is that we will. I’m not going to promise any concrete ship dates here, but it’d
be sorely disappointing if that wouldn’t happen while the calendar still says 2011. 
&lt;/p&gt;
&lt;p&gt;
I just completed writing the functional spec for the feature and it’s worth communicating
how the feature will show up, since there is a tiny chance that the behavioral change
may affect implementations that rely on a particular exception to drive the strategy
of how to perform failover. 
&lt;/p&gt;
&lt;p&gt;
The gist of the Load Balancing spec is that the required changes in your code and
config to get load balancing are zero. With either the NetTcpRelayBinding or any of
the HTTP bindings (WebHttpRelayBinding, etc) as well as the underlying transport binding
elements, you’ll just open up a second (and third and fourth … up to 25) listener
on the same name and instead of getting an AddressAlreadyInUseException as you get
today, you’ll just get automatic load balancing. When a request for your endpoints
shows up at Service Bus, the system will roll the dice on which of the connected listeners
to route the request or connection/session to and perform the necessary handshake
to make that happen.
&lt;/p&gt;
&lt;p&gt;
The bottom line is that we’re effectively making the AddressAlreadyInUseException
go away for the most part. It’ll still be thrown when the listener’s policy settings
don’t match up, i.e. when one listener wants to have Access Control enabled and the
other one doesn’t, but otherwise you’ll just won’t see it anymore. 
&lt;/p&gt;
&lt;p&gt;
The only way this way of just lighting up the feature may get anyone in trouble is
if your application were to rely on that exception in a situation where you’ve got
an active listener on Service Bus on one node and a ‘standby’ listener on another
node that keeps trying to open up a listener into the same address to create a hot/warm
cluster failover scheme &lt;em&gt;and&lt;/em&gt; if the two nodes were tripping over each other
if they were getting traffic concurrently. That doesn’t seem too likely. If you have
questions about this drop me a line here in the comments, by email to clemensv at
microsoft.com or on Twitter @clemensv.&amp;nbsp; 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=bb1fc000-b441-445b-8909-104bd754f60d" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,bb1fc000-b441-445b-8909-104bd754f60d.aspx</comments>
      <category>.NET Services</category>
      <category>AppFabric</category>
      <category>Architecture</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=d41ef7d0-63cd-42ad-8455-ccfcd40997a6</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,d41ef7d0-63cd-42ad-8455-ccfcd40997a6.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,d41ef7d0-63cd-42ad-8455-ccfcd40997a6.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=d41ef7d0-63cd-42ad-8455-ccfcd40997a6</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Our team’s Development Manager MK (Murali Krishnaprasad) and me were interviewed by
Michael Washam on May 2011 CTP release of Windows Azure AppFabric. We discuss new
technologies such as Topics, Queues, Subscriptions and how this relates to doing async
development in the cloud.
</p>
        <p>
 <iframe style="WIDTH: 512px; HEIGHT: 288px" src="http://channel9.msdn.com/Blogs/Server-Side/Understanding-Windows-Azure-AppFabric-Queues/player?w=512&amp;h=288" frameborder="0" scrolling="no"></iframe></p>
        <p>
Republished from <a href="http://channel9.msdn.com/Blogs/Server-Side/Understanding-Windows-Azure-AppFabric-Queues" target="_blank">Channel
9</a></p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d41ef7d0-63cd-42ad-8455-ccfcd40997a6" />
      </body>
      <title>Understanding Windows Azure AppFabric Queues (and Topics)</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,d41ef7d0-63cd-42ad-8455-ccfcd40997a6.aspx</guid>
      <link>http://vasters.com/clemensv/2011/06/11/Understanding+Windows+Azure+AppFabric+Queues+And+Topics.aspx</link>
      <pubDate>Sat, 11 Jun 2011 01:29:21 GMT</pubDate>
      <description>&lt;p&gt;
Our team’s Development Manager MK (Murali Krishnaprasad) and me were interviewed by
Michael Washam on May 2011 CTP release of Windows Azure AppFabric. We discuss new
technologies such as Topics, Queues, Subscriptions and how this relates to doing async
development in the cloud.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&lt;iframe style="WIDTH: 512px; HEIGHT: 288px" src="http://channel9.msdn.com/Blogs/Server-Side/Understanding-Windows-Azure-AppFabric-Queues/player?w=512&amp;amp;h=288" frameborder=0 scrolling=no&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;
Republished from &lt;a href="http://channel9.msdn.com/Blogs/Server-Side/Understanding-Windows-Azure-AppFabric-Queues" target=_blank&gt;Channel
9&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d41ef7d0-63cd-42ad-8455-ccfcd40997a6" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,d41ef7d0-63cd-42ad-8455-ccfcd40997a6.aspx</comments>
      <category>AppFabric</category>
      <category>Architecture</category>
      <category>Technology/ISB</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=d2926b39-5935-449b-927a-2a2421c1aaeb</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,d2926b39-5935-449b-927a-2a2421c1aaeb.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,d2926b39-5935-449b-927a-2a2421c1aaeb.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=d2926b39-5935-449b-927a-2a2421c1aaeb</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <iframe title="YouTube video player" height="390" src="http://www.youtube.com/embed/EqDKRCucIL8" frameborder="0" width="640" allowfullscreen="allowfullscreen">
        </iframe>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d2926b39-5935-449b-927a-2a2421c1aaeb" />
      </body>
      <title>What I do at work &amp;ndash; Cloud and Service Bus for Normal People</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,d2926b39-5935-449b-927a-2a2421c1aaeb.aspx</guid>
      <link>http://vasters.com/clemensv/2011/03/19/What+I+Do+At+Work+Ndash+Cloud+And+Service+Bus+For+Normal+People.aspx</link>
      <pubDate>Sat, 19 Mar 2011 05:06:43 GMT</pubDate>
      <description>&lt;iframe title="YouTube video player" height="390" src="http://www.youtube.com/embed/EqDKRCucIL8" frameborder="0" width="640" allowfullscreen="allowfullscreen"&gt;
&lt;/iframe&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=d2926b39-5935-449b-927a-2a2421c1aaeb" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,d2926b39-5935-449b-927a-2a2421c1aaeb.aspx</comments>
      <category>Architecture</category>
      <category>Azure</category>
      <category>Technology</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=3d2486d4-2bfa-446c-886b-bf336f92c861</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,3d2486d4-2bfa-446c-886b-bf336f92c861.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,3d2486d4-2bfa-446c-886b-bf336f92c861.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=3d2486d4-2bfa-446c-886b-bf336f92c861</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <blockquote>
          <p>
            <em>This post explains an essential class for asynchronous programming that lurks
in the depths of the WCF samples: InputQueue&lt;T&gt;. If you need to write efficient
server-side apps, you should consider reading through this and add InputQueue&lt;T&gt;
to your arsenal.  </em>
          </p>
        </blockquote>
        <p>
Let me start with: This blog post is 4 years late. Sorry! – and with that out of the
way:
</p>
        <p>
The <a href="http://msdn.microsoft.com/wcf">WCF</a> samples ship with several copies
of a class that’s marked as internal in the <em>System.ServiceModel.dll</em> assembly: <em>InputQueue&lt;T&gt;</em>.
Why are these samples – mostly those implementing channel-model extensions – bringing
local copies of this class with them? It’s an essential tool for implementing the
asynchronous call paths of many aspects of channels correctly and efficiently. 
</p>
        <p>
If you look closely enough, the WCF channel infrastructure resembles the Berkeley
Socket model quite a bit – especially on the server side. There’s a channel listener
that’s constructed on the server side and when that is <a href="http://msdn.microsoft.com/en-us/library/ms195524.aspx">opened</a> (usually
under the covers of the WCF ServiceHost) that operation is largely equivalent to calling
‘listen’ on a socket – the network endpoint is ready for business.  On sockets
you’ll then call ‘accept’ to accept the next available socket connection from a client,
in WCF you call ‘<a href="http://msdn.microsoft.com/en-us/library/ms195572.aspx">AcceptChannel</a>’
to accept the next available (session-) channel. On sockets you then call ‘receive’
to obtain bytes, on a channel you call ’<a href="http://msdn.microsoft.com/en-us/library/ms195339.aspx">Receive</a>’
to  obtain a message. 
</p>
        <p>
Before and between calls to '’AcceptChannel’ made by the server-side logic, 
client-initiated connections – and thus channels – may be coming in and queue up for
a bit before they handed out to the next caller of ‘AcceptChannel’, or the asynchronous
equivalent ‘Begin/EndAcceptChannel’ method pair. The number of channels that may be
pending is configured in WCF with the ‘<a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.nettcpbinding.listenbacklog.aspx">ListenBacklog</a>’
property that’s available on most bindings. 
</p>
        <p>
I wrote ‘queue up’ there since that’s precisely what happens – those newly created
channels on top of freshly accepted sockets or HTTP request channels are enqueued
into an <em>InputQueue&lt;T&gt;</em> instance and (Begin-)Accept is implemented as
a dequeue operation on that queue. There are two particular challenges here that make
the regular <em><a href="http://msdn.microsoft.com/en-us/library/7977ey2c.aspx">Queue&lt;T&gt;</a></em> class
from the <em>System.Collections.Generic</em> namespace unsuitable for use in the implementation
of that mechanism: Firstly, the <a href="http://msdn.microsoft.com/en-us/library/1c8bzx97.aspx"><em>Dequeue</em></a> method
there is only available as a synchronous variant and also doesn’t allow for specifying
a timeout. Secondly, the queue implementation doesn’t really help much with implementing
the <em>ListenBacklog</em> quota where not only the length of the queue is limited
to some configured number of entries, but accepting further connections/channels from
the underlying network is also suspended for as long as the queue is at capacity and
needs to resume as soon as the pressure is relieved, i.e. a caller takes a channel
out of the queue. 
</p>
        <p>
To show that <em>InputQueue&lt;T&gt;</em> is a very useful general purpose class even
outside of the context of the WCF channel infrastructure, I’ve lifted a version of
it from one of the most recent WCF channel samples, made a small number of modifications
that I’ll write about later, and created a little sample around it that I’ve attached
to this post. 
</p>
        <p>
The sample I’ll discuss here is simulating parsing/reading IP addresses from a log-file
and then performing a reverse DNS name resolution on those addresses – something that
you’d do in a web-server log-analyzer or as the background task in a blog engine wile
preparing statistics. 
</p>
        <p>
Reverse DNS name resolution is quite interesting since it’s embarrassingly easy to
parallelize and each resolution commonly takes a really long time (4-5 seconds) –whereby
all the work is done elsewhere. The process issuing the queries is mostly sitting
around idle waiting for the response.  Therefore, it’s a good idea to run a number
of DNS requests in parallel, but it’s a terrible idea to have any of these requests
execute as a blocking call and burning a thread. Since we’re assuming that we’re reading
from a log file that requires some parsing, it would also be a spectacularly bad idea
to have multiple concurrent threads compete for access to that file and get into each
other’s way. And since it is a file and we need to lift things up from disk, we probably
shouldn’t do that ‘just in time’ as a DNS resolution step is done, but there should
rather be some data readily waiting for processing.  <em>InputQueue&lt;T&gt; </em>is
enormously helpful in such a scenario.
</p>
        <p>
The key file of the sample code – the implementation of the queue itself aside – is
obviously Program.cs. Here’s Main() :
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">static</span>
            <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[]
args)</pre>
          <pre>{</pre>
          <pre class="alt">
            <span class="kwrd">int</span> maxItemsInQueue = 10;</pre>
          <pre>    InputQueue&lt;IPAddress&gt; logDataQueue = <span class="kwrd">new</span> InputQueue&lt;IPAddress&gt;();</pre>
          <pre class="alt">
            <span class="kwrd">int</span> numResolverLoops = 20;</pre>
          <pre>    ManualResetEvent shutdownCompleteEvent = <span class="kwrd">new</span> ManualResetEvent(<span class="kwrd">false</span>);</pre>
          <pre class="alt">    List&lt;IPAddressResolverLoop&gt; resolverLoops = <span class="kwrd">new</span> List&lt;IPAddressResolverLoop&gt;();</pre>
          <pre> </pre>
          <pre class="alt">    Console.WriteLine(<span class="str">"You can stop the program
by pressing ENTER."</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>
We’re setting up a new <em>InputQueue&lt;IPAddress&gt;</em> here into which we’ll
throw the parsed addresses from our acquisition loop that simulates reading from the
log. The queue’s capacity will be limited to just 10 entries (<em>maxItemsInQueue</em> is
the input value) and we will run 20 'resolver loops’, which are logical threads that
process IP-to-hostname resolution steps.
</p>
        <div class="csharpcode">
          <pre class="alt">    Console.WriteLine(<span class="str">"You
can stop the program by pressing ENTER."</span>);</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="rem">// set up the loop termination callback</span>
          </pre>
          <pre>    WaitCallback loopTerminationCallback = o =&gt;</pre>
          <pre class="alt">    {</pre>
          <pre>
            <span class="kwrd">if</span> (Interlocked.Decrement(<span class="kwrd">ref</span> numResolverLoops)
== 0)</pre>
          <pre class="alt">        {</pre>
          <pre>            shutdownCompleteEvent.Set();</pre>
          <pre class="alt">        }</pre>
          <pre>    };</pre>
          <pre class="alt"> </pre>
          <pre>
            <span class="rem">// set up the resolver loops</span>
          </pre>
          <pre class="alt">
            <span class="kwrd">for</span> (<span class="kwrd">int</span> loop
= 0; loop &lt; numResolverLoops; loop++)</pre>
          <pre>    {</pre>
          <pre class="alt">
            <span class="rem">// add the resolver loop 'i' and set the
done flag when the</span>
          </pre>
          <pre>
            <span class="rem">// last of them terminates</span>
          </pre>
          <pre class="alt">        resolverLoops.Add(</pre>
          <pre>
            <span class="kwrd">new</span> IPAddressResolverLoop(</pre>
          <pre class="alt">                logDataQueue, loop, </pre>
          <pre>                loopTerminationCallback, <span class="kwrd">null</span>));</pre>
          <pre class="alt">    }</pre>
        </div>
        <p>
Next we’re kicking off the resolver loops – we’ll look at these in detail a bit later.
We’ve got a <em>ManualResetEvent</em> lock object that guards the program’s exit until
all these loops have completed and we’re going to set that to signaled once the last
loop completes – that’s what the <em>loopTerminationCallback</em> anonymous method
is for.  We’re registering the method with each of the loops and as they complete
the method gets called and the last call sets the event. Each loop gets a reference
to the <em>logDataQueue </em>from where it gets its work.
</p>
        <div class="csharpcode">
          <pre class="alt">   <span class="rem">// set up
the acquisition loop; the loop auto-starts</span></pre>
          <pre>
            <span class="kwrd">using</span> (LogDataAcquisitionLoop acquisitionLoop =</pre>
          <pre class="alt">
            <span class="kwrd">new</span> LogDataAcquisitionLoop(logDataQueue,
maxItemsInQueue))</pre>
          <pre>    {</pre>
          <pre class="alt">
            <span class="rem">// hang main thread waiting for ENTER</span>
          </pre>
          <pre>        Console.ReadLine();</pre>
          <pre class="alt">        Console.WriteLine(<span class="str">"*** Shutdown initiated."</span>);</pre>
          <pre>    }</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>
Finally we’re starting the acquisition loop that gets the data from the log file.
The loop gets a reference to the <em>logDataQueue</em> where it places the acquired
items and it’s passed the <em>maxItemsInQueue </em>quota that governs how many items
may be read ahead into the queue. Once the user presses the ENTER key, the acquisition
loop object is disposed by ways of exiting the <em>using</em> scope, which stops the
loop.
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="rem"> // shut down the queue;
the resolvers will auto-close</span>
          </pre>
          <pre>
            <span class="rem">// as the queue drains. We don't need to close them here.</span>
          </pre>
          <pre class="alt">    logDataQueue.Shutdown();</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="rem">// wait for all work to complete</span>
          </pre>
          <pre>    shutdownCompleteEvent.WaitOne();</pre>
          <pre class="alt">}</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>
Lastly, the queue is shut down (by fittingly calling <em>Shutdown</em>). Shutdown
closes the queue (all further enqueue operations are absorbed) and causes all pending
readers for which no more entries are available on the queue to unblock immediately 
and return <em>null</em>. The resolver loops will complete their respective jobs and
will terminate whenever they dequeue <em>null</em> from the queue. As they terminate,
they call the registered termination callback (<em>loopTerminationCallback</em> from
above) and that will eventually cause <em>shutdownCompletedEvent</em> to become signaled
as discussed above.
</p>
        <p>
The log-reader simulator isn’t particularly interesting for this sample, even though
one of the goodies is that the simulation executes on an I/O completion port instead
of a managed thread-pool thread – that’s another blog post. The two methods of interest
are Begin/EndGetLogData – all that’s of interest here is that EndGetLogData returns
an <em>IPAddress</em> that’s assumed to be parsed out of a log.
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">class</span> IPAddressLogReaderSimulator</pre>
          <pre>{</pre>
          <pre class="alt">
            <span class="kwrd">public</span> IAsyncResult BeginGetLogData(AsyncCallback
callback, <span class="kwrd">object</span> data);</pre>
          <pre>
            <span class="kwrd">public</span> IPAddress EndGetLogData(IAsyncResult result);</pre>
          <pre class="alt">}</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 simulator is used internally  by the <em>LogDataAcquisitionLoop</em> class
– which we’ll drill into because it implements the throttling mechanism on the queue.
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">class</span> LogDataAcquisitionLoop
: IDisposable</pre>
          <pre>{</pre>
          <pre class="alt">
            <span class="kwrd">readonly</span> IPAddressLogReaderSimulator
ipAddressLogReaderSimulator;</pre>
          <pre>
            <span class="kwrd">readonly</span> InputQueue&lt;IPAddress&gt; logDataQueue;</pre>
          <pre class="alt">
            <span class="kwrd">int</span> maxItemsInQueue;</pre>
          <pre>
            <span class="kwrd">int</span> readingSuspended;</pre>
          <pre class="alt">
            <span class="kwrd">bool</span> shuttingDown;</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">public</span> LogDataAcquisitionLoop(InputQueue&lt;IPAddress&gt;
logDataQueue, <span class="kwrd">int</span> maxItemsInQueue)</pre>
          <pre>    {</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.logDataQueue = logDataQueue;</pre>
          <pre>
            <span class="kwrd">this</span>.maxItemsInQueue = maxItemsInQueue;</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.shuttingDown = <span class="kwrd">false</span>;</pre>
          <pre>
            <span class="kwrd">this</span>.ipAddressLogReaderSimulator = <span class="kwrd">new</span> IPAddressLogReaderSimulator();</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.ipAddressLogReaderSimulator.BeginGetLogData(<font style="BACKGROUND-COLOR: #ffff00"><span class="kwrd">this</span>.LogDataAcquired</font>, <span class="kwrd">null</span>);</pre>
          <pre>    }</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 constructor sets up the shared state of the loop and kicks off the first read
operation on the simulator. Once BeginGetLogData has acquired the first IPAddress
(which will happy very quickly), the <em>LogDataAcquired</em> callback method will
be invoked.  
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">void</span>
            <font style="BACKGROUND-COLOR: #ffff00">LogDataAcquired</font>(IAsyncResult
result)</pre>
          <pre>    {</pre>
          <pre class="alt">        IPAddress address = <span class="kwrd">this</span>.ipAddressLogReaderSimulator.EndGetLogData(result);</pre>
          <pre> </pre>
          <pre class="alt">        Console.WriteLine(<span class="str">"-- added {0}"</span>,
address);</pre>
          <pre>
            <span class="kwrd">this</span>.logDataQueue.EnqueueAndDispatch(address, <span class="kwrd">this</span>.<font style="BACKGROUND-COLOR: #00ff00">LogDataItemDequeued</font>);</pre>
          <pre class="alt">
            <span class="kwrd">if</span> (!<span class="kwrd">this</span>.shuttingDown
&amp;&amp; <span class="kwrd">this</span>.logDataQueue.PendingCount &lt; <span class="kwrd">this</span>.maxItemsInQueue)</pre>
          <pre>        {</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.ipAddressLogReaderSimulator.BeginGetLogData(<span class="kwrd">this</span>.<font style="BACKGROUND-COLOR: #ffff00">LogDataAcquired</font>, <span class="kwrd">null</span>);</pre>
          <pre>        }</pre>
          <pre class="alt">
            <span class="kwrd">else</span>
          </pre>
          <pre>        {</pre>
          <pre class="alt">
            <span class="rem">// the queue will be at the defined
capacity, thus abandon </span>
          </pre>
          <pre>
            <span class="rem">// the read loop - it'll be picked up by LogDataItemDequeued</span>
          </pre>
          <pre class="alt">
            <span class="rem">// as the queue pressure eases</span>
          </pre>
          <pre>            Interlocked.Exchange(<span class="kwrd">ref</span><span class="kwrd">this</span>.<font style="BACKGROUND-COLOR: #ffc000">readingSuspended</font>,
1);</pre>
          <pre class="alt">            Console.WriteLine(<span class="str">"-- suspended reads"</span>);</pre>
          <pre>        }</pre>
          <pre class="alt">    }</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>
        <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 callback method gets the IPAddress and puts it into the queue – using the <em>InputQueue&lt;T&gt;.EnqueueAndDispatch(T,
Action)</em> method. There are two aspects that are quite special about that method
when compared to the regular <em>Queue&lt;T&gt;.Enqueue(T) </em>method. First, it
does take a callback as the second argument alongside the item to be enqueued; second,
the method name isn’t just <em>Enqueue</em>, it also says <em>Dispatch. </em></p>
        <p>
When <em>EnqueueAndDispatch()</em> is called, the item and the callback get put into
an internal item queue – that’s the ‘enqueue’ part. As we will see in context a bit
later in this post, the ‘dequeue’ operation on the queue is the <em>BeginDequeue</em>/<em>EndDequeue</em> asynchronous
method call pair. There can be any number of concurrent <em>BeginDequeue</em> requests
pending on the queue. ‘Pending’ means that the calls – rather their async callbacks
and async state – are registered in another queue internal to <em>InputQueue&lt;T&gt;</em> that
preserves the call order. Thus, <em>BeginDequeue </em>always only puts the async callback
and async state into that queue and returns afterwards. There is no thread spun or
hung. That’s all it does.  
</p>
        <p>
As things go, the best opportunity to service a pending dequeue operation on a queue
is when an item is being enqueued. Consequently, <em>EnqueueAndDispatch()</em> will
first put the item into the internal queue and will then look whether there are registered
waiters and/or readers – waiters are registered by ‘(Begin-)WaitForItem’, readers
are registered by ‘(Begin-)Dequeue’. Since it’s known that there a new item in the
queue now, the operation will iterate overall waiters and complete them – and does
so by invoking their async callbacks, effectively lending the  enqueue operation’s
thread to the waiters. If there’s at least one pending reader, it’ll then pop a message
from the head of the internal item queue and call the reader’s async callback, lending
the enqueue operation’s thread to processing of the dequeue operation. If that just
made your head spin – yes, the item may have been dequeued and processed as <em>EnqueueAndDispatch</em> returns. 
</p>
        <p>
There is an overload for<em> EnqueueAndDispatch()</em> that takes an extra boolean
parameter that lets you cause the dispatch operation to happen on a different thread,
and there is also a <em>EnqueueWithoutDispatch()</em> method that just won’t dispatch
through and a standalone <em>Dispatch()</em> method.  
</p>
        <p>
The callback supplied to <em>EnqueueAndDispatch()</em>, here the <em>LogDataItemDequeued</em> method,
is am <em>Action </em>delegate. The queue will call this callback as the item is being
dequeued and, more precisely, when the item has been removed from the internal item
queue, but just before it is returned to the caller. That turns out to be quite handy.
If you take another look at the <font style="BACKGROUND-COLOR: #ffff00"><em>LogDataAcquired</em></font> method
you’ll notice that we’ve got two alternate code paths after <em>EnqueueAndDispatch()</em>.
The first branch is called when the queue has not reached capacity and it’s not shutting
down. When that’s so, we’re scheduling getting the next log item – otherwise we don’t.
Instead, we set the <em><font style="BACKGROUND-COLOR: #ffffff">readingSuspended</font></em> flag
and quit – effectively terminating and abandoning the loop. So how does that get restarted
when the queue is no longer at capacity? The <em>LogDataItemDequeued</em> callback!
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">void</span>
            <font style="BACKGROUND-COLOR: #00ff00">LogDataItemDequeued</font>()</pre>
          <pre>    {</pre>
          <pre class="alt">
            <span class="rem">// called whenever an item is dequeued.
First we check </span>
          </pre>
          <pre>
            <span class="rem">// whether the queue is no longer full after this </span>
          </pre>
          <pre class="alt">
            <span class="rem">// operation and the we check whether we
need to resume</span>
          </pre>
          <pre>
            <span class="rem">// the read loop.</span>
          </pre>
          <pre class="alt">
            <span class="kwrd">if</span> (!<span class="kwrd">this</span>.shuttingDown
&amp;&amp;</pre>
          <pre>
            <span class="kwrd">this</span>.logDataQueue.PendingCount &lt; <span class="kwrd">this</span>.maxItemsInQueue
&amp;&amp;</pre>
          <pre class="alt">            Interlocked.CompareExchange(<span class="kwrd">ref</span><span class="kwrd">this</span>.readingSuspended,
0, 1) == 1)</pre>
          <pre>        {</pre>
          <pre class="alt">            Console.WriteLine(<span class="str">"-- resuming reads"</span>);</pre>
          <pre>
            <span class="kwrd">this</span>.ipAddressLogReaderSimulator.BeginGetLogData(<span class="kwrd">this</span>.LogDataAcquired, <span class="kwrd">null</span>);</pre>
          <pre class="alt">        }</pre>
          <pre>    }</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 callback gets called for each item that gets dequeued. Which means that we’ll
get an opportunity to restart the loop when it’s been stalled because the queue reached
capacity. So we’re checking here whether the queue isn’t shuttong down and whether
it’s below capacity and if that’s so and the <em>readingSuspended</em> flag is set,
we’re  restarting the read loop. And that’s how the throttle works.
</p>
        <p>
So now we’ve got the data from the log in the queue and we’re throttling nicely so
that we don’t pull too much data into memory. How about taking a look at the DNS resolver
loops that process the data?
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">class</span> IPAddressResolverLoop
: IDisposable</pre>
          <pre>{</pre>
          <pre class="alt">
            <span class="kwrd">readonly</span> InputQueue&lt;IPAddress&gt;
logDataQueue;</pre>
          <pre>
            <span class="kwrd">readonly</span>
            <span class="kwrd">int</span> loop;</pre>
          <pre class="alt">
            <span class="kwrd">readonly</span> WaitCallback loopCompleted;</pre>
          <pre>
            <span class="kwrd">readonly</span>
            <span class="kwrd">object</span> state;</pre>
          <pre class="alt">
            <span class="kwrd">bool</span> shutdown;</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">public</span> IPAddressResolverLoop(InputQueue&lt;IPAddress&gt;
logDataQueue, <span class="kwrd">int</span> loop, WaitCallback loopCompleted, <span class="kwrd">object</span> state)</pre>
          <pre>    {</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.logDataQueue = logDataQueue;</pre>
          <pre>
            <span class="kwrd">this</span>.loop = loop;</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.loopCompleted = loopCompleted;</pre>
          <pre>
            <span class="kwrd">this</span>.state = state;</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.logDataQueue.BeginDequeue(TimeSpan.MaxValue, <span class="kwrd">this</span>.<font style="BACKGROUND-COLOR: #ffff00">IPAddressDequeued</font>, <span class="kwrd">null</span>);</pre>
          <pre>    }</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>
This loop is also implemented as a class and the fields hold shared that that’s initialized
in the constructor. This loop also auto-starts and does so by calling <em>BeginDequeue </em>on
the input queue. As stated above, BeginDequeue  commonly just parks the callback
and returns.
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">void</span>
            <font style="BACKGROUND-COLOR: #ffff00">IPAddressDequeued</font>(IAsyncResult
ar)</pre>
          <pre>    {</pre>
          <pre class="alt">        IPAddress address = <span class="kwrd">this</span>.logDataQueue.EndDequeue(ar);</pre>
          <pre>
            <span class="kwrd">if</span> (!<span class="kwrd">this</span>.shutdown
&amp;&amp; address != <span class="kwrd">null</span>)</pre>
          <pre class="alt">        {</pre>
          <pre>            Console.WriteLine(<span class="str">"-- took {0}"</span>, address);</pre>
          <pre class="alt">            Dns.BeginGetHostEntry(address, <span class="kwrd">this</span>.<font style="BACKGROUND-COLOR: #00ff00">IPAddressResolved</font>, <span class="kwrd">new</span><span class="kwrd">object</span>[]
{ Stopwatch.StartNew(), address });</pre>
          <pre>        }</pre>
          <pre class="alt">
            <span class="kwrd">else</span>
          </pre>
          <pre>        {</pre>
          <pre class="alt">
            <span class="kwrd">this</span>.loopCompleted(<span class="kwrd">this</span>.state);</pre>
          <pre>        }</pre>
          <pre class="alt">    }</pre>
        </div>
        <p>
As an <em>IPAddress</em> is becomes available on the queue, the callback is being
invoked and that’s quite likely on a thread lent by <em>EnqueueAndDispatch</em>()
and therefore sitting  on the thread the log file generator is using to call
back for completion of the <em>BeginGetLogData</em> method if you trace things back.
If we get an address and the value isn’t <em>null</em>, we’ll then proceed to schedule
the DNS lookup via <em>Dns.BeginGetHostEntry</em>. Otherwise we’ll terminate the loop
and call the <em>loopCompleted</em> callback. In Main() that’s the anonymous method
that counts down the loop counter and signals the event when it falls to zero.
</p>
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">void</span>
            <font style="BACKGROUND-COLOR: #00ff00">IPAddressResolved</font>(IAsyncResult
ar)</pre>
          <pre>    {</pre>
          <pre class="alt">        var args = ((<span class="kwrd">object</span>[])ar.AsyncState);</pre>
          <pre>        var stopwatch = (Stopwatch)args[0];</pre>
          <pre class="alt">        var address = (IPAddress)args[1];</pre>
          <pre> </pre>
          <pre class="alt">        stopwatch.Stop();</pre>
          <pre>
            <span class="kwrd">double</span> msecs = stopwatch.ElapsedMilliseconds;</pre>
          <pre class="alt"> </pre>
          <pre>
            <span class="kwrd">try</span>
          </pre>
          <pre class="alt">        {</pre>
          <pre>            IPHostEntry entry = Dns.EndGetHostEntry(ar);</pre>
          <pre class="alt">            Console.WriteLine(<span class="str">"{0}: {1} {2}ms"</span>, <span class="kwrd">this</span>.loop,
entry.HostName, msecs);</pre>
          <pre>        }</pre>
          <pre class="alt">
            <span class="kwrd">catch</span> (SocketException)</pre>
          <pre>        {</pre>
          <pre class="alt">
            <span class="rem">// couldn't resolve. print the literal
address</span>
          </pre>
          <pre>            Console.WriteLine(<span class="str">"{0}: {1} {2}ms"</span>, <span class="kwrd">this</span>.loop,
address, msecs);</pre>
          <pre class="alt">        }</pre>
          <pre>
            <span class="rem">// done with this entry, get the next</span>
          </pre>
          <pre class="alt">
            <span class="kwrd">this</span>.logDataQueue.BeginDequeue(TimeSpan.MaxValue, <span class="kwrd">this</span>.<font style="BACKGROUND-COLOR: #ffff00">IPAddressDequeued</font>, <span class="kwrd">null</span>);</pre>
          <pre>    }</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 <em>IPAddressResolved</em> method just deals with the mechanics of printing out
the result of the lookup and then schedules another <em>BeginDequeue</em> call to
start the next iteration. 
</p>
        <p>
Summary: The enabler for and the core piece of the implementation of this scenario
is <em>InputQueue&lt;T&gt;</em> – the dequeue-callback enables implementing throttling
effectively and the dispatch logic provides an efficient way to leverage threads in
applications that leverage asynchronous programming patterns, especially in I/O driven
situations as illustrated here.
</p>
        <p>
And last but not least – here’s teh codez; project file is for VS2010, throw the files
into a new console app for VS2008 and mark the project to allow unsafe code (for the
I/O completion thread pool code).
</p>
        <p>
          <a href="http://vasters.com/clemensv/content/binary/UsingInputQueue.zip">UsingInputQueue.zip
(13.85 KB)</a> 
</p>
        <p>
or if you'd rather have a version of InputQueue that is using the regular thread pool, <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=35ec8682-d5fd-4bc3-a51a-d8ad115a8792&amp;displaylang=en">download
the WCF samples</a> and look for InputQueue.cs.
</p>
        <p>
[The sample code posted here is subject to the Windows SDK sample code license]
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=3d2486d4-2bfa-446c-886b-bf336f92c861" />
      </body>
      <title>The Magical Input Queue Of T (aka InputQueue&amp;lt;T&amp;gt;)</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,3d2486d4-2bfa-446c-886b-bf336f92c861.aspx</guid>
      <link>http://vasters.com/clemensv/2010/09/12/The+Magical+Input+Queue+Of+T+Aka+InputQueueltTgt.aspx</link>
      <pubDate>Sun, 12 Sep 2010 07:29:23 GMT</pubDate>
      <description>&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;This post explains an essential class for asynchronous programming that lurks
in the depths of the WCF samples: InputQueue&amp;lt;T&amp;gt;. If you need to write efficient
server-side apps, you should consider reading through this and add InputQueue&amp;lt;T&amp;gt;
to your arsenal.&amp;nbsp; &lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Let me start with: This blog post is 4 years late. Sorry! – and with that out of the
way:
&lt;/p&gt;
&lt;p&gt;
The &lt;a href="http://msdn.microsoft.com/wcf"&gt;WCF&lt;/a&gt; samples ship with several copies
of a class that’s marked as internal in the &lt;em&gt;System.ServiceModel.dll&lt;/em&gt; assembly: &lt;em&gt;InputQueue&amp;lt;T&amp;gt;&lt;/em&gt;.
Why are these samples – mostly those implementing channel-model extensions – bringing
local copies of this class with them? It’s an essential tool for implementing the
asynchronous call paths of many aspects of channels correctly and efficiently. 
&lt;/p&gt;
&lt;p&gt;
If you look closely enough, the WCF channel infrastructure resembles the Berkeley
Socket model quite a bit – especially on the server side. There’s a channel listener
that’s constructed on the server side and when that is &lt;a href="http://msdn.microsoft.com/en-us/library/ms195524.aspx"&gt;opened&lt;/a&gt; (usually
under the covers of the WCF ServiceHost) that operation is largely equivalent to calling
‘listen’ on a socket – the network endpoint is ready for business.&amp;nbsp; On sockets
you’ll then call ‘accept’ to accept the next available socket connection from a client,
in WCF you call ‘&lt;a href="http://msdn.microsoft.com/en-us/library/ms195572.aspx"&gt;AcceptChannel&lt;/a&gt;’
to accept the next available (session-) channel. On sockets you then call ‘receive’
to obtain bytes, on a channel you call ’&lt;a href="http://msdn.microsoft.com/en-us/library/ms195339.aspx"&gt;Receive&lt;/a&gt;’
to&amp;nbsp; obtain a message. 
&lt;/p&gt;
&lt;p&gt;
Before and between calls to '’AcceptChannel’ made by the server-side logic,&amp;nbsp;
client-initiated connections – and thus channels – may be coming in and queue up for
a bit before they handed out to the next caller of ‘AcceptChannel’, or the asynchronous
equivalent ‘Begin/EndAcceptChannel’ method pair. The number of channels that may be
pending is configured in WCF with the ‘&lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.nettcpbinding.listenbacklog.aspx"&gt;ListenBacklog&lt;/a&gt;’
property that’s available on most bindings. 
&lt;/p&gt;
&lt;p&gt;
I wrote ‘queue up’ there since that’s precisely what happens – those newly created
channels on top of freshly accepted sockets or HTTP request channels are enqueued
into an &lt;em&gt;InputQueue&amp;lt;T&amp;gt;&lt;/em&gt; instance and (Begin-)Accept is implemented as
a dequeue operation on that queue. There are two particular challenges here that make
the regular &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/7977ey2c.aspx"&gt;Queue&amp;lt;T&amp;gt;&lt;/a&gt;&lt;/em&gt; class
from the &lt;em&gt;System.Collections.Generic&lt;/em&gt; namespace unsuitable for use in the implementation
of that mechanism: Firstly, the &lt;a href="http://msdn.microsoft.com/en-us/library/1c8bzx97.aspx"&gt;&lt;em&gt;Dequeue&lt;/em&gt;&lt;/a&gt; method
there is only available as a synchronous variant and also doesn’t allow for specifying
a timeout. Secondly, the queue implementation doesn’t really help much with implementing
the &lt;em&gt;ListenBacklog&lt;/em&gt; quota where not only the length of the queue is limited
to some configured number of entries, but accepting further connections/channels from
the underlying network is also suspended for as long as the queue is at capacity and
needs to resume as soon as the pressure is relieved, i.e. a caller takes a channel
out of the queue. 
&lt;/p&gt;
&lt;p&gt;
To show that &lt;em&gt;InputQueue&amp;lt;T&amp;gt;&lt;/em&gt; is a very useful general purpose class even
outside of the context of the WCF channel infrastructure, I’ve lifted a version of
it from one of the most recent WCF channel samples, made a small number of modifications
that I’ll write about later, and created a little sample around it that I’ve attached
to this post. 
&lt;/p&gt;
&lt;p&gt;
The sample I’ll discuss here is simulating parsing/reading IP addresses from a log-file
and then performing a reverse DNS name resolution on those addresses – something that
you’d do in a web-server log-analyzer or as the background task in a blog engine wile
preparing statistics. 
&lt;/p&gt;
&lt;p&gt;
Reverse DNS name resolution is quite interesting since it’s embarrassingly easy to
parallelize and each resolution commonly takes a really long time (4-5 seconds) –whereby
all the work is done elsewhere. The process issuing the queries is mostly sitting
around idle waiting for the response.&amp;nbsp; Therefore, it’s a good idea to run a number
of DNS requests in parallel, but it’s a terrible idea to have any of these requests
execute as a blocking call and burning a thread. Since we’re assuming that we’re reading
from a log file that requires some parsing, it would also be a spectacularly bad idea
to have multiple concurrent threads compete for access to that file and get into each
other’s way. And since it is a file and we need to lift things up from disk, we probably
shouldn’t do that ‘just in time’ as a DNS resolution step is done, but there should
rather be some data readily waiting for processing.&amp;nbsp; &lt;em&gt;InputQueue&amp;lt;T&amp;gt; &lt;/em&gt;is
enormously helpful in such a scenario.
&lt;/p&gt;
&lt;p&gt;
The key file of the sample code – the implementation of the queue itself aside – is
obviously Program.cs. Here’s Main() :
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&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;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;int&lt;/span&gt; maxItemsInQueue = 10;&lt;/pre&gt;
&lt;pre&gt;    InputQueue&amp;lt;IPAddress&amp;gt; logDataQueue = &lt;span class=kwrd&gt;new&lt;/span&gt; InputQueue&amp;lt;IPAddress&amp;gt;();&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;int&lt;/span&gt; numResolverLoops = 20;&lt;/pre&gt;
&lt;pre&gt;    ManualResetEvent shutdownCompleteEvent = &lt;span class=kwrd&gt;new&lt;/span&gt; ManualResetEvent(&lt;span class=kwrd&gt;false&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class=alt&gt;    List&amp;lt;IPAddressResolverLoop&amp;gt; resolverLoops = &lt;span class=kwrd&gt;new&lt;/span&gt; List&amp;lt;IPAddressResolverLoop&amp;gt;();&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class=alt&gt;    Console.WriteLine(&lt;span class=str&gt;"You can stop the program by
pressing ENTER."&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;
We’re setting up a new &lt;em&gt;InputQueue&amp;lt;IPAddress&amp;gt;&lt;/em&gt; here into which we’ll
throw the parsed addresses from our acquisition loop that simulates reading from the
log. The queue’s capacity will be limited to just 10 entries (&lt;em&gt;maxItemsInQueue&lt;/em&gt; is
the input value) and we will run 20 'resolver loops’, which are logical threads that
process IP-to-hostname resolution steps.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;    Console.WriteLine(&lt;span class=str&gt;"You can
stop the program by pressing ENTER."&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=rem&gt;// set up the loop termination callback&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    WaitCallback loopTerminationCallback = o =&amp;gt;&lt;/pre&gt;
&lt;pre class=alt&gt;    {&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;if&lt;/span&gt; (Interlocked.Decrement(&lt;span class=kwrd&gt;ref&lt;/span&gt; numResolverLoops)
== 0)&lt;/pre&gt;
&lt;pre class=alt&gt;        {&lt;/pre&gt;
&lt;pre&gt;            shutdownCompleteEvent.Set();&lt;/pre&gt;
&lt;pre class=alt&gt;        }&lt;/pre&gt;
&lt;pre&gt;    };&lt;/pre&gt;
&lt;pre class=alt&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=rem&gt;// set up the resolver loops&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;for&lt;/span&gt; (&lt;span class=kwrd&gt;int&lt;/span&gt; loop =
0; loop &amp;lt; numResolverLoops; loop++)&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=rem&gt;// add the resolver loop 'i' and set the done
flag when the&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=rem&gt;// last of them terminates&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;        resolverLoops.Add(&lt;/pre&gt;
&lt;pre&gt;            &lt;span class=kwrd&gt;new&lt;/span&gt; IPAddressResolverLoop(&lt;/pre&gt;
&lt;pre class=alt&gt;                logDataQueue, loop, &lt;/pre&gt;
&lt;pre&gt;                loopTerminationCallback, &lt;span class=kwrd&gt;null&lt;/span&gt;));&lt;/pre&gt;
&lt;pre class=alt&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Next we’re kicking off the resolver loops – we’ll look at these in detail a bit later.
We’ve got a &lt;em&gt;ManualResetEvent&lt;/em&gt; lock object that guards the program’s exit until
all these loops have completed and we’re going to set that to signaled once the last
loop completes – that’s what the &lt;em&gt;loopTerminationCallback&lt;/em&gt; anonymous method
is for.&amp;nbsp; We’re registering the method with each of the loops and as they complete
the method gets called and the last call sets the event. Each loop gets a reference
to the &lt;em&gt;logDataQueue &lt;/em&gt;from where it gets its work.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;&amp;nbsp;&amp;nbsp; &lt;span class=rem&gt;// set up the acquisition
loop; the loop auto-starts&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=kwrd&gt;using&lt;/span&gt; (LogDataAcquisitionLoop acquisitionLoop =&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;new&lt;/span&gt; LogDataAcquisitionLoop(logDataQueue,
maxItemsInQueue))&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=rem&gt;// hang main thread waiting for ENTER&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        Console.ReadLine();&lt;/pre&gt;
&lt;pre class=alt&gt;        Console.WriteLine(&lt;span class=str&gt;"*** Shutdown initiated."&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&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;
Finally we’re starting the acquisition loop that gets the data from the log file.
The loop gets a reference to the &lt;em&gt;logDataQueue&lt;/em&gt; where it places the acquired
items and it’s passed the &lt;em&gt;maxItemsInQueue &lt;/em&gt;quota that governs how many items
may be read ahead into the queue. Once the user presses the ENTER key, the acquisition
loop object is disposed by ways of exiting the &lt;em&gt;using&lt;/em&gt; scope, which stops the
loop.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;&lt;span class=rem&gt; // shut down the queue; the
resolvers will auto-close&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=rem&gt;// as the queue drains. We don't need to close them here.&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;    logDataQueue.Shutdown();&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=rem&gt;// wait for all work to complete&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    shutdownCompleteEvent.WaitOne();&lt;/pre&gt;
&lt;pre class=alt&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;
Lastly, the queue is shut down (by fittingly calling &lt;em&gt;Shutdown&lt;/em&gt;). Shutdown
closes the queue (all further enqueue operations are absorbed) and causes all pending
readers for which no more entries are available on the queue to unblock immediately&amp;nbsp;
and return &lt;em&gt;null&lt;/em&gt;. The resolver loops will complete their respective jobs and
will terminate whenever they dequeue &lt;em&gt;null&lt;/em&gt; from the queue. As they terminate,
they call the registered termination callback (&lt;em&gt;loopTerminationCallback&lt;/em&gt; from
above) and that will eventually cause &lt;em&gt;shutdownCompletedEvent&lt;/em&gt; to become signaled
as discussed above.
&lt;/p&gt;
&lt;p&gt;
The log-reader simulator isn’t particularly interesting for this sample, even though
one of the goodies is that the simulation executes on an I/O completion port instead
of a managed thread-pool thread – that’s another blog post. The two methods of interest
are Begin/EndGetLogData – all that’s of interest here is that EndGetLogData returns
an &lt;em&gt;IPAddress&lt;/em&gt; that’s assumed to be parsed out of a log.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;&lt;span class=kwrd&gt;class&lt;/span&gt; IPAddressLogReaderSimulator&lt;/pre&gt;
&lt;pre&gt;{&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;public&lt;/span&gt; IAsyncResult BeginGetLogData(AsyncCallback
callback, &lt;span class=kwrd&gt;object&lt;/span&gt; data);&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=kwrd&gt;public&lt;/span&gt; IPAddress EndGetLogData(IAsyncResult result);&lt;/pre&gt;
&lt;pre class=alt&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 simulator is used internally&amp;nbsp; by the &lt;em&gt;LogDataAcquisitionLoop&lt;/em&gt; class
– which we’ll drill into because it implements the throttling mechanism on the queue.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;&lt;span class=kwrd&gt;class&lt;/span&gt; LogDataAcquisitionLoop
: IDisposable&lt;/pre&gt;
&lt;pre&gt;{&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;readonly&lt;/span&gt; IPAddressLogReaderSimulator ipAddressLogReaderSimulator;&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=kwrd&gt;readonly&lt;/span&gt; InputQueue&amp;lt;IPAddress&amp;gt; logDataQueue;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;int&lt;/span&gt; maxItemsInQueue;&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=kwrd&gt;int&lt;/span&gt; readingSuspended;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;bool&lt;/span&gt; shuttingDown;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;public&lt;/span&gt; LogDataAcquisitionLoop(InputQueue&amp;lt;IPAddress&amp;gt;
logDataQueue, &lt;span class=kwrd&gt;int&lt;/span&gt; maxItemsInQueue)&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue = logDataQueue;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.maxItemsInQueue = maxItemsInQueue;&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.shuttingDown = &lt;span class=kwrd&gt;false&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.ipAddressLogReaderSimulator = &lt;span class=kwrd&gt;new&lt;/span&gt; IPAddressLogReaderSimulator();&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.ipAddressLogReaderSimulator.BeginGetLogData(&lt;font style="BACKGROUND-COLOR: #ffff00"&gt;&lt;span class=kwrd&gt;this&lt;/span&gt;.LogDataAcquired&lt;/font&gt;, &lt;span class=kwrd&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&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 constructor sets up the shared state of the loop and kicks off the first read
operation on the simulator. Once BeginGetLogData has acquired the first IPAddress
(which will happy very quickly), the &lt;em&gt;LogDataAcquired&lt;/em&gt; callback method will
be invoked.&amp;nbsp; 
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;void&lt;/span&gt; &lt;font style="BACKGROUND-COLOR: #ffff00"&gt;LogDataAcquired&lt;/font&gt;(IAsyncResult
result)&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        IPAddress address = &lt;span class=kwrd&gt;this&lt;/span&gt;.ipAddressLogReaderSimulator.EndGetLogData(result);&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class=alt&gt;        Console.WriteLine(&lt;span class=str&gt;"-- added {0}"&lt;/span&gt;, address);&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue.EnqueueAndDispatch(address, &lt;span class=kwrd&gt;this&lt;/span&gt;.&lt;font style="BACKGROUND-COLOR: #00ff00"&gt;LogDataItemDequeued&lt;/font&gt;);&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;if&lt;/span&gt; (!&lt;span class=kwrd&gt;this&lt;/span&gt;.shuttingDown
&amp;amp;&amp;amp; &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue.PendingCount &amp;lt; &lt;span class=kwrd&gt;this&lt;/span&gt;.maxItemsInQueue)&lt;/pre&gt;
&lt;pre&gt;        {&lt;/pre&gt;
&lt;pre class=alt&gt;            &lt;span class=kwrd&gt;this&lt;/span&gt;.ipAddressLogReaderSimulator.BeginGetLogData(&lt;span class=kwrd&gt;this&lt;/span&gt;.&lt;font style="BACKGROUND-COLOR: #ffff00"&gt;LogDataAcquired&lt;/font&gt;, &lt;span class=kwrd&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;        }&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        {&lt;/pre&gt;
&lt;pre class=alt&gt;            &lt;span class=rem&gt;// the queue will be at the defined capacity,
thus abandon &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;            &lt;span class=rem&gt;// the read loop - it'll be picked up by LogDataItemDequeued&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;            &lt;span class=rem&gt;// as the queue pressure eases&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;            Interlocked.Exchange(&lt;span class=kwrd&gt;ref&lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.&lt;font style="BACKGROUND-COLOR: #ffc000"&gt;readingSuspended&lt;/font&gt;,
1);&lt;/pre&gt;
&lt;pre class=alt&gt;            Console.WriteLine(&lt;span class=str&gt;"-- suspended reads"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;        }&lt;/pre&gt;
&lt;pre class=alt&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;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 callback method gets the IPAddress and puts it into the queue – using the &lt;em&gt;InputQueue&amp;lt;T&amp;gt;.EnqueueAndDispatch(T,
Action)&lt;/em&gt; method. There are two aspects that are quite special about that method
when compared to the regular &lt;em&gt;Queue&amp;lt;T&amp;gt;.Enqueue(T) &lt;/em&gt;method. First, it
does take a callback as the second argument alongside the item to be enqueued; second,
the method name isn’t just &lt;em&gt;Enqueue&lt;/em&gt;, it also says &lt;em&gt;Dispatch. &lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
When &lt;em&gt;EnqueueAndDispatch()&lt;/em&gt; is called, the item and the callback get put into
an internal item queue – that’s the ‘enqueue’ part. As we will see in context a bit
later in this post, the ‘dequeue’ operation on the queue is the &lt;em&gt;BeginDequeue&lt;/em&gt;/&lt;em&gt;EndDequeue&lt;/em&gt; asynchronous
method call pair. There can be any number of concurrent &lt;em&gt;BeginDequeue&lt;/em&gt; requests
pending on the queue. ‘Pending’ means that the calls – rather their async callbacks
and async state – are registered in another queue internal to &lt;em&gt;InputQueue&amp;lt;T&amp;gt;&lt;/em&gt; that
preserves the call order. Thus, &lt;em&gt;BeginDequeue &lt;/em&gt;always only puts the async callback
and async state into that queue and returns afterwards. There is no thread spun or
hung. That’s all it does.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
As things go, the best opportunity to service a pending dequeue operation on a queue
is when an item is being enqueued. Consequently, &lt;em&gt;EnqueueAndDispatch()&lt;/em&gt; will
first put the item into the internal queue and will then look whether there are registered
waiters and/or readers – waiters are registered by ‘(Begin-)WaitForItem’, readers
are registered by ‘(Begin-)Dequeue’. Since it’s known that there a new item in the
queue now, the operation will iterate overall waiters and complete them – and does
so by invoking their async callbacks, effectively lending the&amp;nbsp; enqueue operation’s
thread to the waiters. If there’s at least one pending reader, it’ll then pop a message
from the head of the internal item queue and call the reader’s async callback, lending
the enqueue operation’s thread to processing of the dequeue operation. If that just
made your head spin – yes, the item may have been dequeued and processed as &lt;em&gt;EnqueueAndDispatch&lt;/em&gt; returns. 
&lt;/p&gt;
&lt;p&gt;
There is an overload for&lt;em&gt; EnqueueAndDispatch()&lt;/em&gt; that takes an extra boolean
parameter that lets you cause the dispatch operation to happen on a different thread,
and there is also a &lt;em&gt;EnqueueWithoutDispatch()&lt;/em&gt; method that just won’t dispatch
through and a standalone &lt;em&gt;Dispatch()&lt;/em&gt; method.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
The callback supplied to &lt;em&gt;EnqueueAndDispatch()&lt;/em&gt;, here the &lt;em&gt;LogDataItemDequeued&lt;/em&gt; method,
is am &lt;em&gt;Action &lt;/em&gt;delegate. The queue will call this callback as the item is being
dequeued and, more precisely, when the item has been removed from the internal item
queue, but just before it is returned to the caller. That turns out to be quite handy.
If you take another look at the &lt;font style="BACKGROUND-COLOR: #ffff00"&gt;&lt;em&gt;LogDataAcquired&lt;/em&gt;&lt;/font&gt; method
you’ll notice that we’ve got two alternate code paths after &lt;em&gt;EnqueueAndDispatch()&lt;/em&gt;.
The first branch is called when the queue has not reached capacity and it’s not shutting
down. When that’s so, we’re scheduling getting the next log item – otherwise we don’t.
Instead, we set the &lt;em&gt;&lt;font style="BACKGROUND-COLOR: #ffffff"&gt;readingSuspended&lt;/font&gt;&lt;/em&gt; flag
and quit – effectively terminating and abandoning the loop. So how does that get restarted
when the queue is no longer at capacity? The &lt;em&gt;LogDataItemDequeued&lt;/em&gt; callback!
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;void&lt;/span&gt; &lt;font style="BACKGROUND-COLOR: #00ff00"&gt;LogDataItemDequeued&lt;/font&gt;()&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=rem&gt;// called whenever an item is dequeued. First
we check &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=rem&gt;// whether the queue is no longer full after this &lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=rem&gt;// operation and the we check whether we need
to resume&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=rem&gt;// the read loop.&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;if&lt;/span&gt; (!&lt;span class=kwrd&gt;this&lt;/span&gt;.shuttingDown
&amp;amp;&amp;amp;&lt;/pre&gt;
&lt;pre&gt;            &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue.PendingCount &amp;lt; &lt;span class=kwrd&gt;this&lt;/span&gt;.maxItemsInQueue
&amp;amp;&amp;amp;&lt;/pre&gt;
&lt;pre class=alt&gt;            Interlocked.CompareExchange(&lt;span class=kwrd&gt;ref&lt;/span&gt; &lt;span class=kwrd&gt;this&lt;/span&gt;.readingSuspended,
0, 1) == 1)&lt;/pre&gt;
&lt;pre&gt;        {&lt;/pre&gt;
&lt;pre class=alt&gt;            Console.WriteLine(&lt;span class=str&gt;"-- resuming reads"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;            &lt;span class=kwrd&gt;this&lt;/span&gt;.ipAddressLogReaderSimulator.BeginGetLogData(&lt;span class=kwrd&gt;this&lt;/span&gt;.LogDataAcquired, &lt;span class=kwrd&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class=alt&gt;        }&lt;/pre&gt;
&lt;pre&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 callback gets called for each item that gets dequeued. Which means that we’ll
get an opportunity to restart the loop when it’s been stalled because the queue reached
capacity. So we’re checking here whether the queue isn’t shuttong down and whether
it’s below capacity and if that’s so and the &lt;em&gt;readingSuspended&lt;/em&gt; flag is set,
we’re&amp;nbsp; restarting the read loop. And that’s how the throttle works.
&lt;/p&gt;
&lt;p&gt;
So now we’ve got the data from the log in the queue and we’re throttling nicely so
that we don’t pull too much data into memory. How about taking a look at the DNS resolver
loops that process the data?
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;&lt;span class=kwrd&gt;class&lt;/span&gt; IPAddressResolverLoop
: IDisposable&lt;/pre&gt;
&lt;pre&gt;{&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;readonly&lt;/span&gt; InputQueue&amp;lt;IPAddress&amp;gt; logDataQueue;&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=kwrd&gt;readonly&lt;/span&gt; &lt;span class=kwrd&gt;int&lt;/span&gt; loop;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;readonly&lt;/span&gt; WaitCallback loopCompleted;&lt;/pre&gt;
&lt;pre&gt;    &lt;span class=kwrd&gt;readonly&lt;/span&gt; &lt;span class=kwrd&gt;object&lt;/span&gt; state;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;bool&lt;/span&gt; shutdown;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;public&lt;/span&gt; IPAddressResolverLoop(InputQueue&amp;lt;IPAddress&amp;gt;
logDataQueue, &lt;span class=kwrd&gt;int&lt;/span&gt; loop, WaitCallback loopCompleted, &lt;span class=kwrd&gt;object&lt;/span&gt; state)&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue = logDataQueue;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.loop = loop;&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.loopCompleted = loopCompleted;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.state = state;&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue.BeginDequeue(TimeSpan.MaxValue, &lt;span class=kwrd&gt;this&lt;/span&gt;.&lt;font style="BACKGROUND-COLOR: #ffff00"&gt;IPAddressDequeued&lt;/font&gt;, &lt;span class=kwrd&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&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;
This loop is also implemented as a class and the fields hold shared that that’s initialized
in the constructor. This loop also auto-starts and does so by calling &lt;em&gt;BeginDequeue &lt;/em&gt;on
the input queue. As stated above, BeginDequeue&amp;nbsp; commonly just parks the callback
and returns.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;void&lt;/span&gt; &lt;font style="BACKGROUND-COLOR: #ffff00"&gt;IPAddressDequeued&lt;/font&gt;(IAsyncResult
ar)&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        IPAddress address = &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue.EndDequeue(ar);&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;if&lt;/span&gt; (!&lt;span class=kwrd&gt;this&lt;/span&gt;.shutdown &amp;amp;&amp;amp;
address != &lt;span class=kwrd&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre class=alt&gt;        {&lt;/pre&gt;
&lt;pre&gt;            Console.WriteLine(&lt;span class=str&gt;"-- took {0}"&lt;/span&gt;, address);&lt;/pre&gt;
&lt;pre class=alt&gt;            Dns.BeginGetHostEntry(address, &lt;span class=kwrd&gt;this&lt;/span&gt;.&lt;font style="BACKGROUND-COLOR: #00ff00"&gt;IPAddressResolved&lt;/font&gt;, &lt;span class=kwrd&gt;new&lt;/span&gt; &lt;span class=kwrd&gt;object&lt;/span&gt;[]
{ Stopwatch.StartNew(), address });&lt;/pre&gt;
&lt;pre&gt;        }&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        {&lt;/pre&gt;
&lt;pre class=alt&gt;            &lt;span class=kwrd&gt;this&lt;/span&gt;.loopCompleted(&lt;span class=kwrd&gt;this&lt;/span&gt;.state);&lt;/pre&gt;
&lt;pre&gt;        }&lt;/pre&gt;
&lt;pre class=alt&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
As an &lt;em&gt;IPAddress&lt;/em&gt; is becomes available on the queue, the callback is being
invoked and that’s quite likely on a thread lent by &lt;em&gt;EnqueueAndDispatch&lt;/em&gt;()
and therefore sitting&amp;nbsp; on the thread the log file generator is using to call
back for completion of the &lt;em&gt;BeginGetLogData&lt;/em&gt; method if you trace things back.
If we get an address and the value isn’t &lt;em&gt;null&lt;/em&gt;, we’ll then proceed to schedule
the DNS lookup via &lt;em&gt;Dns.BeginGetHostEntry&lt;/em&gt;. Otherwise we’ll terminate the loop
and call the &lt;em&gt;loopCompleted&lt;/em&gt; callback. In Main() that’s the anonymous method
that counts down the loop counter and signals the event when it falls to zero.
&lt;/p&gt;
&lt;div class=csharpcode&gt;&lt;pre class=alt&gt;    &lt;span class=kwrd&gt;void&lt;/span&gt; &lt;font style="BACKGROUND-COLOR: #00ff00"&gt;IPAddressResolved&lt;/font&gt;(IAsyncResult
ar)&lt;/pre&gt;
&lt;pre&gt;    {&lt;/pre&gt;
&lt;pre class=alt&gt;        var args = ((&lt;span class=kwrd&gt;object&lt;/span&gt;[])ar.AsyncState);&lt;/pre&gt;
&lt;pre&gt;        var stopwatch = (Stopwatch)args[0];&lt;/pre&gt;
&lt;pre class=alt&gt;        var address = (IPAddress)args[1];&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class=alt&gt;        stopwatch.Stop();&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;double&lt;/span&gt; msecs = stopwatch.ElapsedMilliseconds;&lt;/pre&gt;
&lt;pre class=alt&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=kwrd&gt;try&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;        {&lt;/pre&gt;
&lt;pre&gt;            IPHostEntry entry = Dns.EndGetHostEntry(ar);&lt;/pre&gt;
&lt;pre class=alt&gt;            Console.WriteLine(&lt;span class=str&gt;"{0}: {1} {2}ms"&lt;/span&gt;, &lt;span class=kwrd&gt;this&lt;/span&gt;.loop,
entry.HostName, msecs);&lt;/pre&gt;
&lt;pre&gt;        }&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;catch&lt;/span&gt; (SocketException)&lt;/pre&gt;
&lt;pre&gt;        {&lt;/pre&gt;
&lt;pre class=alt&gt;            &lt;span class=rem&gt;// couldn't resolve. print the literal
address&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;            Console.WriteLine(&lt;span class=str&gt;"{0}: {1} {2}ms"&lt;/span&gt;, &lt;span class=kwrd&gt;this&lt;/span&gt;.loop,
address, msecs);&lt;/pre&gt;
&lt;pre class=alt&gt;        }&lt;/pre&gt;
&lt;pre&gt;        &lt;span class=rem&gt;// done with this entry, get the next&lt;/span&gt;&lt;/pre&gt;
&lt;pre class=alt&gt;        &lt;span class=kwrd&gt;this&lt;/span&gt;.logDataQueue.BeginDequeue(TimeSpan.MaxValue, &lt;span class=kwrd&gt;this&lt;/span&gt;.&lt;font style="BACKGROUND-COLOR: #ffff00"&gt;IPAddressDequeued&lt;/font&gt;, &lt;span class=kwrd&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&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 &lt;em&gt;IPAddressResolved&lt;/em&gt; method just deals with the mechanics of printing out
the result of the lookup and then schedules another &lt;em&gt;BeginDequeue&lt;/em&gt; call to
start the next iteration. 
&lt;/p&gt;
&lt;p&gt;
Summary: The enabler for and the core piece of the implementation of this scenario
is &lt;em&gt;InputQueue&amp;lt;T&amp;gt;&lt;/em&gt; – the dequeue-callback enables implementing throttling
effectively and the dispatch logic provides an efficient way to leverage threads in
applications that leverage asynchronous programming patterns, especially in I/O driven
situations as illustrated here.
&lt;/p&gt;
&lt;p&gt;
And last but not least – here’s teh codez; project file is for VS2010, throw the files
into a new console app for VS2008 and mark the project to allow unsafe code (for the
I/O completion thread pool code).
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://vasters.com/clemensv/content/binary/UsingInputQueue.zip"&gt;UsingInputQueue.zip
(13.85 KB)&lt;/a&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
or if you'd rather have a version of InputQueue that is using the regular thread pool, &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=35ec8682-d5fd-4bc3-a51a-d8ad115a8792&amp;amp;displaylang=en"&gt;download
the WCF samples&lt;/a&gt;&amp;nbsp;and look for InputQueue.cs.
&lt;/p&gt;
&lt;p&gt;
[The sample code posted here is subject to the Windows SDK sample code license]
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=3d2486d4-2bfa-446c-886b-bf336f92c861" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,3d2486d4-2bfa-446c-886b-bf336f92c861.aspx</comments>
      <category>Architecture</category>
      <category>Technology/CLR</category>
      <category>Technology/WCF</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=29ec4fe1-65d8-467e-8360-ce50a2ccd1ff</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,29ec4fe1-65d8-467e-8360-ce50a2ccd1ff.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,29ec4fe1-65d8-467e-8360-ce50a2ccd1ff.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=29ec4fe1-65d8-467e-8360-ce50a2ccd1ff</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I put the slides for my talks at NT Konferenca 2010 <a href="http://cid-123ccd2a7ab10107.skydrive.live.com/browse.aspx/NT%20Konferenca%202010">on
SkyDrive</a>. The major difference from my <a href="http://vasters.com/clemensv/PermaLink,guid,cb6599da-5785-4186-8ca1-68a0f32f4495.aspx">APAC
slides</a> is that I had to put compute and storage <a href="http://cid-123ccd2a7ab10107.skydrive.live.com/self.aspx/NT%20Konferenca%202010/NTK2010-Azure-CapabilitiesAndTips.pptx">into
one deck</a> due to the conference schedule, but instead of purely consolidating and
cutting down the slide count,  I also incorporated some common patterns coming
out from debates in Asia and added slides on predictable and dynamic scaling as well
as on multitenancy. Sadly, I need to rush through all that in 45 minutes
today. 
</p>
        <p>
          <iframe style="PADDING-BOTTOM: 0px; BACKGROUND-COLOR: #fcfcfc; PADDING-LEFT: 0px; WIDTH: 98px; PADDING-RIGHT: 0px; HEIGHT: 115px; PADDING-TOP: 0px" title="Preview" marginheight="0" src="http://cid-123ccd2a7ab10107.skydrive.live.com/embedicon.aspx/NT%20Konferenca%202010" frameborder="0" marginwidth="0" scrolling="no">
          </iframe>
        </p>
        <p>
 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=29ec4fe1-65d8-467e-8360-ce50a2ccd1ff" />
      </body>
      <title>NT Konferenca 2010 - Windows Azure Slidedecks</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,29ec4fe1-65d8-467e-8360-ce50a2ccd1ff.aspx</guid>
      <link>http://vasters.com/clemensv/2010/05/25/NT+Konferenca+2010+Windows+Azure+Slidedecks.aspx</link>
      <pubDate>Tue, 25 May 2010 07:08:59 GMT</pubDate>
      <description>&lt;p&gt;
I put the slides for my talks at NT Konferenca 2010 &lt;a href="http://cid-123ccd2a7ab10107.skydrive.live.com/browse.aspx/NT%20Konferenca%202010"&gt;on
SkyDrive&lt;/a&gt;.&amp;nbsp;The major difference from my&amp;nbsp;&lt;a href="http://vasters.com/clemensv/PermaLink,guid,cb6599da-5785-4186-8ca1-68a0f32f4495.aspx"&gt;APAC
slides&lt;/a&gt;&amp;nbsp;is that I had to put compute and storage&amp;nbsp;&lt;a href="http://cid-123ccd2a7ab10107.skydrive.live.com/self.aspx/NT%20Konferenca%202010/NTK2010-Azure-CapabilitiesAndTips.pptx"&gt;into
one deck&lt;/a&gt; due to the conference schedule, but instead of purely consolidating and
cutting down the slide count,&amp;nbsp; I also incorporated some common patterns coming
out from debates in Asia and added slides on predictable and dynamic scaling as well
as on&amp;nbsp;multitenancy. Sadly, I need to rush&amp;nbsp;through all that in&amp;nbsp;45 minutes
today. 
&lt;/p&gt;
&lt;p&gt;
&lt;iframe style="PADDING-BOTTOM: 0px; BACKGROUND-COLOR: #fcfcfc; PADDING-LEFT: 0px; WIDTH: 98px; PADDING-RIGHT: 0px; HEIGHT: 115px; PADDING-TOP: 0px" title=Preview marginheight=0 src="http://cid-123ccd2a7ab10107.skydrive.live.com/embedicon.aspx/NT%20Konferenca%202010" frameborder=0 marginwidth=0 scrolling=no&gt;
&lt;/iframe&gt;
&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=29ec4fe1-65d8-467e-8360-ce50a2ccd1ff" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,29ec4fe1-65d8-467e-8360-ce50a2ccd1ff.aspx</comments>
      <category>AppFabric</category>
      <category>Architecture</category>
      <category>Azure</category>
      <category>Talks</category>
      <category>Technology</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=cb6599da-5785-4186-8ca1-68a0f32f4495</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,cb6599da-5785-4186-8ca1-68a0f32f4495.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,cb6599da-5785-4186-8ca1-68a0f32f4495.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=cb6599da-5785-4186-8ca1-68a0f32f4495</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I'm on a tour through several countries right now and I'm talking to ISVs about
the Windows Azure platform, its capabilities and the many opportunities ISVs have
to transform the way they do business by moving to the cloud. The first day of the
events is an introduction to the platform at the capability level; it's not a coding
class, that would be impossible to fit.
</p>
        <p>
          <a href="http://cid-123ccd2a7ab10107.skydrive.live.com/browse.aspx/APAC%20Azure%20ISV">I've
shared the slides on SkyDrive</a>. Steal liberally if you find the material useful.
</p>
        <p>
 
</p>
        <iframe style="PADDING-BOTTOM: 0px; BACKGROUND-COLOR: #fcfcfc; PADDING-LEFT: 0px; WIDTH: 98px; PADDING-RIGHT: 0px; HEIGHT: 115px; PADDING-TOP: 0px" title="Preview" marginheight="0" src="http://cid-123ccd2a7ab10107.skydrive.live.com/embedicon.aspx/APAC%20Azure%20ISV" frameborder="0" marginwidth="0" scrolling="no">
        </iframe>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=cb6599da-5785-4186-8ca1-68a0f32f4495" />
      </body>
      <title>Windows Azure Speaking Tour Slides</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,cb6599da-5785-4186-8ca1-68a0f32f4495.aspx</guid>
      <link>http://vasters.com/clemensv/2010/05/16/Windows+Azure+Speaking+Tour+Slides.aspx</link>
      <pubDate>Sun, 16 May 2010 08:31:17 GMT</pubDate>
      <description>&lt;p&gt;
I'm on a tour through several countries right now&amp;nbsp;and I'm talking to ISVs about
the Windows Azure platform, its capabilities and the many opportunities ISVs have
to transform the way they do business by moving to the cloud. The first day of the
events is an introduction to the platform at the capability level; it's not a coding
class, that would be impossible to fit.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://cid-123ccd2a7ab10107.skydrive.live.com/browse.aspx/APAC%20Azure%20ISV"&gt;I've
shared the slides on SkyDrive&lt;/a&gt;. Steal liberally if you find the material&amp;nbsp;useful.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;iframe style="PADDING-BOTTOM: 0px; BACKGROUND-COLOR: #fcfcfc; PADDING-LEFT: 0px; WIDTH: 98px; PADDING-RIGHT: 0px; HEIGHT: 115px; PADDING-TOP: 0px" title=Preview marginheight=0 src="http://cid-123ccd2a7ab10107.skydrive.live.com/embedicon.aspx/APAC%20Azure%20ISV" frameborder=0 marginwidth=0 scrolling=no&gt;
&lt;/iframe&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=cb6599da-5785-4186-8ca1-68a0f32f4495" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,cb6599da-5785-4186-8ca1-68a0f32f4495.aspx</comments>
      <category>AppFabric</category>
      <category>Architecture</category>
      <category>Azure</category>
      <category>Talks</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=26dc5df1-8b8c-4f71-8765-8904e584505b</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,26dc5df1-8b8c-4f71-8765-8904e584505b.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,26dc5df1-8b8c-4f71-8765-8904e584505b.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=26dc5df1-8b8c-4f71-8765-8904e584505b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Anyone using the .NET Service Bus should take a good look at the <a href="http://blogs.aws.net/atc/post/SocketShifter-Warping-the-Internet-Space-Time-Continuum-with-the-Azure-NET-Service-Bus.aspx">SocketShifter
project</a> started by Rob Blackwell and Richard Prodger from AWS in the UK. AWS stands
for <a href="http://www.aws.net">Active Web Solutions</a>, not for the "other" AWS.
The full project is up on <a href="http://socketshifter.codeplex.com/">Codeplex</a>.
</p>
        <p>
What makes SocketShifter significant is that it takes the network abstraction of SOAP,
WS-Addressing, and the Service Bus full circle and layers the very bottom of that
stack - plain TCP connections - as a virtualization on top of the the stack. In other
words: SocketShifter allows you to create full-fidelity, bi-directional socket connections
through the .NET Service Bus.
</p>
        <p>
We've created something very similar to SocketShifter last year (we're using
it for a few internal purposes), but haven't made it public so far. I'm glad that
the AWS folks built this, so that you get to play with it.   
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=26dc5df1-8b8c-4f71-8765-8904e584505b" />
      </body>
      <title>SocketShifter - Network virtualization over the .NET Service Bus</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,26dc5df1-8b8c-4f71-8765-8904e584505b.aspx</guid>
      <link>http://vasters.com/clemensv/2009/07/06/SocketShifter+Network+Virtualization+Over+The+NET+Service+Bus.aspx</link>
      <pubDate>Mon, 06 Jul 2009 16:06:48 GMT</pubDate>
      <description>&lt;p&gt;
Anyone using the .NET Service Bus should take a good look at the &lt;a href="http://blogs.aws.net/atc/post/SocketShifter-Warping-the-Internet-Space-Time-Continuum-with-the-Azure-NET-Service-Bus.aspx"&gt;SocketShifter
project&lt;/a&gt; started by Rob Blackwell and Richard Prodger from AWS in the UK. AWS stands
for &lt;a href="http://www.aws.net"&gt;Active Web Solutions&lt;/a&gt;, not for the "other" AWS.
The full project is up on &lt;a href="http://socketshifter.codeplex.com/"&gt;Codeplex&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
What makes SocketShifter significant is that it takes the network abstraction of SOAP,
WS-Addressing, and the Service Bus full circle and layers the very bottom of that
stack - plain TCP connections - as a virtualization on top of the the stack. In other
words: SocketShifter allows you to create full-fidelity, bi-directional socket connections
through the .NET Service Bus.
&lt;/p&gt;
&lt;p&gt;
We've created something very similar to SocketShifter last year&amp;nbsp;(we're using
it for a few internal purposes), but haven't made it public so far. I'm glad that
the AWS folks&amp;nbsp;built this, so that you get to play with it.&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=26dc5df1-8b8c-4f71-8765-8904e584505b" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,26dc5df1-8b8c-4f71-8765-8904e584505b.aspx</comments>
      <category>.NET Services</category>
      <category>Architecture</category>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=83edb04a-5696-401c-a919-8c1f379d130c</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,83edb04a-5696-401c-a919-8c1f379d130c.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,83edb04a-5696-401c-a919-8c1f379d130c.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=83edb04a-5696-401c-a919-8c1f379d130c</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:2fa07bff-113a-425e-98ba-b07fc54b0584" class="wlWriterEditableSmartContent">
          <p>
.NET Service Bus Reverse Web Proxy: <a href="http://vasters.com/clemensv/content/binary/WindowsLiveWriter/NETServicesMarch2009CTPHostaPublicWebs_9AB2/ServiceBusReverseWebProxy.zip">Click
here to download the source</a></p>
        </div>
        <p>
          <strong>
          </strong>
        </p>
        <p>
          <a href="http://vasters.com/clemensv/content/binary/WindowsLiveWriter/NETServicesMarch2009CTPHostaPublicWebs_9AB2/image_2.png">
            <img style="BORDER-RIGHT-WIDTH: 0px; MARGIN: 10px 20px 10px 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" align="left" src="http://vasters.com/clemensv/content/binary/WindowsLiveWriter/NETServicesMarch2009CTPHostaPublicWebs_9AB2/image_thumb.png" width="383" height="500" />
          </a>
        </p>
        <p style="MARGIN-TOP: 5px">
Using the application/service built from the sample linked at the top of this post
you can <strong>host</strong> a <strong>publicly discoverable and accessible website</strong> or
Web service <strong>from your Windows notebook</strong> or desktop machine from within
most network environments <strong>without</strong> having to <strong>open up a port
on the firewall</strong>, mapping a port on your NAT, or using some type of dynamic
DNS service to make the site discoverable. All those essential connectivity features
are provided by the .NET Service Bus and with the help of the included sample code.
</p>
        <p style="MARGIN-TOP: 5px">
I’m intentionally not bundling this up as a conveniently installable binary along
with a nice configuration UI – that’s not my role here. If <strong>you</strong> want
to grab the code and make it part of a cool personal media sharing app, provide external
access to a departmental enterprise app, put a prototype out there for a client to
play with, host a web service you want to show off, or or provide an installable version
with a nice configuration UI – go ahead. 
</p>
        <p style="MARGIN-TOP: 5px">
The attached sample application/service has two key capabilities that I’ve repeatedly
been asked for:
</p>
        <p style="MARGIN-TOP: 5px">
a) It is a <strong>reverse web proxy</strong> that can run either as a console application
or as a Windows (NT-) service. The reverse web proxy can sit in front of any web server
and forward requests to it. I’ve tested this only with IIS as the backend, but I don’t
see a reason why this shouldn’t work with Apache or the Web Server built into some
J2EE application server. 
</p>
        <p style="MARGIN-TOP: 5px">
b) It is a scripting <strong>policy host</strong> that projects the <em>crossdomain.xml</em> and <em>ClientPolicyAccess.xml</em> files
required by <strong>Adobe Flash</strong> and <strong>Microsoft Silverlight</strong> into
the root of a .NET Services namespace, permitting cross-domain script access from
Flash and Silverlight for all endpoints hosted within the namespace. You can easily
adjust the code in the sample to restrict access to particular resources within the
namespace.
</p>
        <p style="MARGIN-TOP: 5px">
The fundamental architecture is illustrated in the picture. The web application that
you want to project out to the public internet sits on some web server on your machine.
“Your machine” may be a desktop machine at home or at work or a notebook in a hotel
lobby or an airport on WiFi. As long as you’ve got line-of-sight to the .NET Service
Bus and the TCP ports 828 and 818 are available for outbound traffic, you’re good.
The reverse web proxy app will map any local HTTP server to a name in the .NET Service
Bus and forward the traffic between the .NET Service Bus and the HTTP server. The
client (any web browser, but also any HTTP Web Service client) will talk to the .NET
Service Bus at the given name, the traffic flows to the reverse proxy on your machine
and from there to the HTTP server.
</p>
        <p style="MARGIN-TOP: 5px">
I’m hosting (for a few days) a sample <a href="http://www.dasblog.info">dasBlog</a> site
instance at <a title="http://clemensv6.servicebus.windows.net/dasblog/" href="http://clemensv6.servicebus.windows.net/dasblog/">http://clemensv6.servicebus.windows.net/dasblog/</a>.
The hosting machine for that blog is one of my personal machines. It’s got a local
network address assigned by DHCP, it’s not listed in any NAT mappings, and it’s local
Firewall isn’t even open for inbound HTTP traffic.  
</p>
        <p style="MARGIN-TOP: 5px">
          <strong>How to install, build, and run</strong>
        </p>
        <p style="MARGIN-TOP: 5px">
As a prerequisite you will need three things:
</p>
        <ol>
          <li>
            <div style="MARGIN-TOP: 5px">Visual Studio 2008 SP1 with the .NET Framework 3.5 SP1.
</div>
          </li>
          <li>
            <div style="MARGIN-TOP: 5px">A .NET Services project account. The quickest route is
to go to <a href="http://portal.ex.azure.microsoft.com">http://portal.ex.azure.microsoft.com</a> and
click “Sign up”. The approval/provisioning is pretty much instantaneous (plus 20 seconds
for the provisioning to run through) once you provide your Windows Live ID. No more
access codes.
</div>
          </li>
          <li>
            <div style="MARGIN-TOP: 5px">The .NET Services SDK for the March 2009 CTP. <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=8D1D1D5E-1332-4186-B33F-26D053759E49&amp;displaylang=en">Click
here to get it</a>.
</div>
          </li>
        </ol>
        <p style="MARGIN-TOP: 5px">
Unpack the files, and open <em>ServiceBusReverseWebProxy.sln</em> with Visual Studio
2008. In the ServiceBusReverseWebProxy project, find the <strong>app.config</strong> file
and open it. Here’s where you need to put your project name and password and where
you map your sites:
</p>
        <pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  1: <span style="COLOR: #0000ff">&lt;?</span>xml
version="1.0" encoding="utf-8" <span style="COLOR: #0000ff">?&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  2: <span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">configuration</span><span style="COLOR: #0000ff">&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  3:     <span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">configSections</span><span style="COLOR: #0000ff">&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  4:         <span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">section</span><span style="COLOR: #ff0000">name</span>=<span style="COLOR: #0000ff">"reverseWebProxy"</span></pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  5:                  <span style="COLOR: #ff0000">type</span>=<span style="COLOR: #0000ff">"Microsoft.Samples.ServiceBusReverseWebProxy.ReverseWebProxySection,
ServiceBusReverseWebProxy"</span><span style="COLOR: #0000ff">/&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  6:     <span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">configSections</span><span style="COLOR: #0000ff">&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  7:     <span style="COLOR: #008000">&lt;!--
Add your .NET Services project account information here --&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  8:     <span style="COLOR: #008000">&lt;!--
Create a project at http://portal.ex.azure.microsoft.com/ --&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  9:     <span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">reverseWebProxy</span><span style="COLOR: #ff0000">netServicesProjectName</span>=<span style="COLOR: #0000ff">"!!myproject!!"</span><span style="COLOR: #ff0000">netServicesProjectPassword</span>=<span style="COLOR: #0000ff">"!!mypassword!!"</span></pre>
          <pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"> 10:                      <span style="COLOR: #ff0000">enableSilverlightPolicy</span>=<span style="COLOR: #0000ff">"true"</span><span style="COLOR: #0000ff">&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"> 11:     <span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">pathMappings</span><span style="COLOR: #0000ff">&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"> 12:       <span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">add</span><span style="COLOR: #ff0000">namespacePath</span>=<span style="COLOR: #0000ff">"mysite"</span><span style="COLOR: #ff0000">localUri</span>=<span style="COLOR: #0000ff">"http://localhost/mysite/"</span><span style="COLOR: #0000ff">/&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"> 13:     <span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">pathMappings</span><span style="COLOR: #0000ff">&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"> 14:   <span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">reverseWebProxy</span><span style="COLOR: #0000ff">&gt;</span></pre>
          <pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"> 15: <span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">configuration</span><span style="COLOR: #0000ff">&gt;</span></pre>
        </pre>
        <p>
Put your .NET Services project/solution name into the <em>netServicesProjectName</em> and
the password into <em>netServicesProjectPassword</em>. 
</p>
        <p>
Then pick a local HTTP server or site and give it a name in your .NET Service Bus
namespace. That mapping is done in the <em>&lt;pathMappings&gt;</em> section. There
are a few things that are important to note here:
</p>
        <ol>
          <li>
If your project name were ‘<strong>clemensv6</strong>’ and you map some local URI
to the namespacePath ‘<strong>dasBlog</strong>’, the resulting .NET Service Bus URI
would be <a title="http://clemensv6.servicebus.windows.net/dasblog/" href="http://clemensv6.servicebus.windows.net/dasblog/">http://<strong>clemensv6</strong>.servicebus.windows.net/<strong>dasblog</strong>/</a>. 
</li>
          <li>
The web application should only emit relative paths for links or, otherwise, should
have a way to specify the external host address for links. That means that the web
application needs to be able to deal with the presence of a reverse proxy. There is
no content-level URL rewriter in this sample that would make any corrections to HTML
or XML that’s handed upstream. DasBlog allows you to specify the blog site address
as some external address and therefore satisfies that requirements. 
</li>
          <li>
Redirects and any other HTTP responses that emit the HTTP ‘Location’ header or any
other HTTP headers where URIs are returned are rewritten to map the internal view
to the external view. 
</li>
          <li>
If you set <em>enableSilverlightPolicy</em> to <em>true</em>, there will be <em>crossdomain.xml</em> and <em>ClientPolicyAccess.xml</em> endpoints
projected into the root of your project’s namespace, ie. <a title="http://clemensv6.servicebus.windows.net/dasblog/" href="http://clemensv6.servicebus.windows.net/crossdomain.xml">http://clemensv6.servicebus.windows.net/crossdomain.xml</a><strong></strong></li>
        </ol>
        <p>
Build. Run. 
</p>
        <p>
By default, the ServiceBusReverseWebProxy.exe application will simply run as a console
application. If you use <strong>installutil –i ServiceBusReverseWebProxy.exe</strong> the
application will be installed as a Windows Service. The default identity that it is
installed under is ‘NETWORK SERVICE’. In restricted networks with constrained IPSec
policies (such as the Microsoft Corporate Network), you may have to use a user account
instead. You may also have to use some special Firewall-gateway software such as the
ISA Firewall client to allow for outbound access to ports 828 and 818. 
</p>
        <p>
The actual application code isn’t really all that complicated. The ‘beef’ is in <strong>ReverseWebProxy.cs</strong>.
What might be surprising here is that this class doesn’t use the WCF Service Model,
but is using naked WCF channels for the upstream traffic to .NET Services and it’s
using HttpWebRequest for the downstream traffic to the local Web Server. The reason
for using channels is that the app is never doing any processing on the messages,
so the channel model is the most straightforward and efficient way. The reason for
using HttpWebRequest is that you can’t suppress auto-redirects on a WCF HTTP client.
Since the stack needs to be completely transparent to redirects so that it’s the browser
client up on top that gets redirected instead of someone on the way, I simply couldn’t
use a WCF channel downstream. Seems to be one of these edge cases that the WCF team
downstairs didn’t think anyone would ever need.
</p>
        <p>
Let me know whether and how this works for you. Share the code, improve it, re-blog,
let me know. @clemensv on Twitter, same name @microsoft.com for email.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=83edb04a-5696-401c-a919-8c1f379d130c" />
      </body>
      <title>.NET Services March 2009 CTP: Host a Public Website At The Kitchen Table or from a Coffee Shop! No Kidding.</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,83edb04a-5696-401c-a919-8c1f379d130c.aspx</guid>
      <link>http://vasters.com/clemensv/2009/04/05/NET+Services+March+2009+CTP+Host+A+Public+Website+At+The+Kitchen+Table+Or+From+A+Coffee+Shop+No+Kidding.aspx</link>
      <pubDate>Sun, 05 Apr 2009 19:41:36 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:2fa07bff-113a-425e-98ba-b07fc54b0584 class=wlWriterEditableSmartContent&gt;
&lt;p&gt;
.NET Service Bus Reverse Web Proxy: &lt;a href="http://vasters.com/clemensv/content/binary/WindowsLiveWriter/NETServicesMarch2009CTPHostaPublicWebs_9AB2/ServiceBusReverseWebProxy.zip"&gt;Click
here to download the source&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://vasters.com/clemensv/content/binary/WindowsLiveWriter/NETServicesMarch2009CTPHostaPublicWebs_9AB2/image_2.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; MARGIN: 10px 20px 10px 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image align=left src="http://vasters.com/clemensv/content/binary/WindowsLiveWriter/NETServicesMarch2009CTPHostaPublicWebs_9AB2/image_thumb.png" width=383 height=500&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
Using the application/service built from the sample linked at the top of this post
you can &lt;strong&gt;host&lt;/strong&gt; a &lt;strong&gt;publicly discoverable and accessible website&lt;/strong&gt; or
Web service &lt;strong&gt;from your Windows notebook&lt;/strong&gt; or desktop machine from within
most network environments &lt;strong&gt;without&lt;/strong&gt; having to &lt;strong&gt;open up a port
on the firewall&lt;/strong&gt;, mapping a port on your NAT, or using some type of dynamic
DNS service to make the site discoverable. All those essential connectivity features
are provided by the .NET Service Bus and with the help of the included sample code.
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
I’m intentionally not bundling this up as a conveniently installable binary along
with a nice configuration UI – that’s not my role here. If &lt;strong&gt;you&lt;/strong&gt; want
to grab the code and make it part of a cool personal media sharing app, provide external
access to a departmental enterprise app, put a prototype out there for a client to
play with, host a web service you want to show off, or or provide an installable version
with a nice configuration UI – go ahead. 
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
The attached sample application/service has two key capabilities that I’ve repeatedly
been asked for:
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
a) It is a &lt;strong&gt;reverse web proxy&lt;/strong&gt; that can run either as a console application
or as a Windows (NT-) service. The reverse web proxy can sit in front of any web server
and forward requests to it. I’ve tested this only with IIS as the backend, but I don’t
see a reason why this shouldn’t work with Apache or the Web Server built into some
J2EE application server. 
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
b) It is a scripting &lt;strong&gt;policy host&lt;/strong&gt; that projects the &lt;em&gt;crossdomain.xml&lt;/em&gt; and &lt;em&gt;ClientPolicyAccess.xml&lt;/em&gt; files
required by &lt;strong&gt;Adobe Flash&lt;/strong&gt; and &lt;strong&gt;Microsoft Silverlight&lt;/strong&gt; into
the root of a .NET Services namespace, permitting cross-domain script access from
Flash and Silverlight for all endpoints hosted within the namespace. You can easily
adjust the code in the sample to restrict access to particular resources within the
namespace.
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
The fundamental architecture is illustrated in the picture. The web application that
you want to project out to the public internet sits on some web server on your machine.
“Your machine” may be a desktop machine at home or at work or a notebook in a hotel
lobby or an airport on WiFi. As long as you’ve got line-of-sight to the .NET Service
Bus and the TCP ports 828 and 818 are available for outbound traffic, you’re good.
The reverse web proxy app will map any local HTTP server to a name in the .NET Service
Bus and forward the traffic between the .NET Service Bus and the HTTP server. The
client (any web browser, but also any HTTP Web Service client) will talk to the .NET
Service Bus at the given name, the traffic flows to the reverse proxy on your machine
and from there to the HTTP server.
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
I’m hosting (for a few days) a sample &lt;a href="http://www.dasblog.info"&gt;dasBlog&lt;/a&gt; site
instance at &lt;a title=http://clemensv6.servicebus.windows.net/dasblog/ href="http://clemensv6.servicebus.windows.net/dasblog/"&gt;http://clemensv6.servicebus.windows.net/dasblog/&lt;/a&gt;.
The hosting machine for that blog is one of my personal machines. It’s got a local
network address assigned by DHCP, it’s not listed in any NAT mappings, and it’s local
Firewall isn’t even open for inbound HTTP traffic.&amp;nbsp; 
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
&lt;strong&gt;How to install, build, and run&lt;/strong&gt;
&lt;/p&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
As a prerequisite you will need three things:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div style="MARGIN-TOP: 5px"&gt;Visual Studio 2008 SP1 with the .NET Framework 3.5 SP1.
&lt;/div&gt;
&lt;li&gt;
&lt;div style="MARGIN-TOP: 5px"&gt;A .NET Services project account. The quickest route is
to go to &lt;a href="http://portal.ex.azure.microsoft.com"&gt;http://portal.ex.azure.microsoft.com&lt;/a&gt; and
click “Sign up”. The approval/provisioning is pretty much instantaneous (plus 20 seconds
for the provisioning to run through) once you provide your Windows Live ID. No more
access codes.
&lt;/div&gt;
&lt;li&gt;
&lt;div style="MARGIN-TOP: 5px"&gt;The .NET Services SDK for the March 2009 CTP. &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=8D1D1D5E-1332-4186-B33F-26D053759E49&amp;amp;displaylang=en"&gt;Click
here to get it&lt;/a&gt;.
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="MARGIN-TOP: 5px"&gt;
Unpack the files, and open &lt;em&gt;ServiceBusReverseWebProxy.sln&lt;/em&gt; with Visual Studio
2008. In the ServiceBusReverseWebProxy project, find the &lt;strong&gt;app.config&lt;/strong&gt; file
and open it. Here’s where you need to put your project name and password and where
you map your sites:
&lt;/p&gt;
&lt;pre&gt;&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  1: &lt;span style="COLOR: #0000ff"&gt;&amp;lt;?&lt;/span&gt;xml
version="1.0" encoding="utf-8" &lt;span style="COLOR: #0000ff"&gt;?&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  2: &lt;span style="COLOR: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;configuration&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  3:     &lt;span style="COLOR: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;configSections&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  4:         &lt;span style="COLOR: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;section&lt;/span&gt; &lt;span style="COLOR: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="COLOR: #0000ff"&gt;"reverseWebProxy"&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  5:                  &lt;span style="COLOR: #ff0000"&gt;type&lt;/span&gt;=&lt;span style="COLOR: #0000ff"&gt;"Microsoft.Samples.ServiceBusReverseWebProxy.ReverseWebProxySection,
ServiceBusReverseWebProxy"&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  6:     &lt;span style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;configSections&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  7:     &lt;span style="COLOR: #008000"&gt;&amp;lt;!--
Add your .NET Services project account information here --&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  8:     &lt;span style="COLOR: #008000"&gt;&amp;lt;!--
Create a project at http://portal.ex.azure.microsoft.com/ --&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt;  9:     &lt;span style="COLOR: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;reverseWebProxy&lt;/span&gt; &lt;span style="COLOR: #ff0000"&gt;netServicesProjectName&lt;/span&gt;=&lt;span style="COLOR: #0000ff"&gt;"!!myproject!!"&lt;/span&gt; &lt;span style="COLOR: #ff0000"&gt;netServicesProjectPassword&lt;/span&gt;=&lt;span style="COLOR: #0000ff"&gt;"!!mypassword!!"&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt; 10:                      &lt;span style="COLOR: #ff0000"&gt;enableSilverlightPolicy&lt;/span&gt;=&lt;span style="COLOR: #0000ff"&gt;"true"&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt; 11:     &lt;span style="COLOR: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;pathMappings&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt; 12:       &lt;span style="COLOR: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;add&lt;/span&gt; &lt;span style="COLOR: #ff0000"&gt;namespacePath&lt;/span&gt;=&lt;span style="COLOR: #0000ff"&gt;"mysite"&lt;/span&gt; &lt;span style="COLOR: #ff0000"&gt;localUri&lt;/span&gt;=&lt;span style="COLOR: #0000ff"&gt;"http://localhost/mysite/"&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt; 13:     &lt;span style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;pathMappings&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt; 14:   &lt;span style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;reverseWebProxy&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;pre style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"&gt; 15: &lt;span style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #800000"&gt;configuration&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;
Put your .NET Services project/solution name into the &lt;em&gt;netServicesProjectName&lt;/em&gt; and
the password into &lt;em&gt;netServicesProjectPassword&lt;/em&gt;. 
&lt;/p&gt;
&lt;p&gt;
Then pick a local HTTP server or site and give it a name in your .NET Service Bus
namespace. That mapping is done in the &lt;em&gt;&amp;lt;pathMappings&amp;gt;&lt;/em&gt; section. There
are a few things that are important to note here:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
If your project name were ‘&lt;strong&gt;clemensv6&lt;/strong&gt;’ and you map some local URI
to the namespacePath ‘&lt;strong&gt;dasBlog&lt;/strong&gt;’, the resulting .NET Service Bus URI
would be &lt;a title=http://clemensv6.servicebus.windows.net/dasblog/ href="http://clemensv6.servicebus.windows.net/dasblog/"&gt;http://&lt;strong&gt;clemensv6&lt;/strong&gt;.servicebus.windows.net/&lt;strong&gt;dasblog&lt;/strong&gt;/&lt;/a&gt;. 
&lt;li&gt;
The web application should only emit relative paths for links or, otherwise, should
have a way to specify the external host address for links. That means that the web
application needs to be able to deal with the presence of a reverse proxy. There is
no content-level URL rewriter in this sample that would make any corrections to HTML
or XML that’s handed upstream. DasBlog allows you to specify the blog site address
as some external address and therefore satisfies that requirements. 
&lt;li&gt;
Redirects and any other HTTP responses that emit the HTTP ‘Location’ header or any
other HTTP headers where URIs are returned are rewritten to map the internal view
to the external view. 
&lt;li&gt;
If you set &lt;em&gt;enableSilverlightPolicy&lt;/em&gt; to &lt;em&gt;true&lt;/em&gt;, there will be &lt;em&gt;crossdomain.xml&lt;/em&gt; and &lt;em&gt;ClientPolicyAccess.xml&lt;/em&gt; endpoints
projected into the root of your project’s namespace, ie. &lt;a title=http://clemensv6.servicebus.windows.net/dasblog/ href="http://clemensv6.servicebus.windows.net/crossdomain.xml"&gt;http://clemensv6.servicebus.windows.net/crossdomain.xml&lt;/a&gt;&lt;strong&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Build. Run. 
&lt;/p&gt;
&lt;p&gt;
By default, the ServiceBusReverseWebProxy.exe application will simply run as a console
application. If you use &lt;strong&gt;installutil –i ServiceBusReverseWebProxy.exe&lt;/strong&gt; the
application will be installed as a Windows Service. The default identity that it is
installed under is ‘NETWORK SERVICE’. In restricted networks with constrained IPSec
policies (such as the Microsoft Corporate Network), you may have to use a user account
instead. You may also have to use some special Firewall-gateway software such as the
ISA Firewall client to allow for outbound access to ports 828 and 818. 
&lt;/p&gt;
&lt;p&gt;
The actual application code isn’t really all that complicated. The ‘beef’ is in &lt;strong&gt;ReverseWebProxy.cs&lt;/strong&gt;.
What might be surprising here is that this class doesn’t use the WCF Service Model,
but is using naked WCF channels for the upstream traffic to .NET Services and it’s
using HttpWebRequest for the downstream traffic to the local Web Server. The reason
for using channels is that the app is never doing any processing on the messages,
so the channel model is the most straightforward and efficient way. The reason for
using HttpWebRequest is that you can’t suppress auto-redirects on a WCF HTTP client.
Since the stack needs to be completely transparent to redirects so that it’s the browser
client up on top that gets redirected instead of someone on the way, I simply couldn’t
use a WCF channel downstream. Seems to be one of these edge cases that the WCF team
downstairs didn’t think anyone would ever need.
&lt;/p&gt;
&lt;p&gt;
Let me know whether and how this works for you. Share the code, improve it, re-blog,
let me know. @clemensv on Twitter, same name @microsoft.com for email.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=83edb04a-5696-401c-a919-8c1f379d130c" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,83edb04a-5696-401c-a919-8c1f379d130c.aspx</comments>
      <category>.NET Services</category>
      <category>Architecture</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=634b72d9-e200-45de-82db-2ae4c8ef947e</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,634b72d9-e200-45de-82db-2ae4c8ef947e.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,634b72d9-e200-45de-82db-2ae4c8ef947e.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=634b72d9-e200-45de-82db-2ae4c8ef947e</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>… <a href="http://de.wikipedia.org/wiki/Auf_der_Mauer,_auf_der_Lauer">seht Euch
mal die Wa an, wie die Wa ta kann. Auf der Mauer auf der Lauer sitzt ‘ne kleine Wa!</a>.</em>
        </p>
        <p>
It’s a German children’s song. The song starts out with “… sitzt ‘ne kleine Wanze”
(bedbug) and with each verse you leave off a letter: Wanz, Wan, Wa, W, – silence. 
</p>
        <p>
I’ll do the same here, but not with a bedbug:
</p>
        <p>
Let’s sing:
</p>
        <p>
          <font face="Courier New">&lt;soap:Envelope xmlns:soap=”” xmlns:wsaddr=”” xmlns:wsrm=””
xmlns:wsu=”” xmlns:app=””&gt;<br />
   &lt;soap:Header&gt;<br />
         &lt;addr:Action&gt;http://tempuri.org/1.0/Status.set&lt;/addr:Action&gt;<br />
         &lt;wsrm:Sequence&gt;<br />
              &lt;wsrm:Identifier&gt;urn:session-id&lt;/wsrm:Identifier&gt;<br />
              &lt;wsrm:MessageNumber&gt;5&lt;/wsrm:MessageNumber&gt;<br />
          &lt;/wsrm:Sequence&gt;<br />
          &lt;wsse:Security xmlns:wsse=”…”&gt;<br />
              
&lt;wsse:BinarySecurityToken ValueType="</font>
          <font face="Courier New">http://tempuri.org#CustomToken</font>
          <font face="Courier New">" 
<br />
                                        
EncodingType="...#Base64Binary" wsu:Id=" MyID "&gt;<br />
                         
FHUIORv...<br />
               
&lt;/wsse:BinarySecurityToken&gt;<br />
              
&lt;ds:Signature&gt;<br />
                 
&lt;ds:SignedInfo&gt; 
<br />
                     
&lt;ds:CanonicalizationMethod Algorithm="</font>
          <font face="Courier New">http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;</font>
          <br />
          <font face="Courier New">                     
&lt;ds:SignatureMethod Algorithm="</font>
          <font face="Courier New">http://www.w3.org/2000/09/xmldsig#md5"/</font>
          <font face="Courier New">&gt;  
<br />
                     
&lt;ds:Reference URI="#MsgBody"&gt;<br />
                           
&lt;ds:DigestMethod  Algorithm="</font>
          <font face="Courier New">http://www.w3.org/2000/09/xmldsig#md5"/&gt;</font>
          <font face="Courier New"> <br />
                           
&lt;ds:DigestValue&gt;LyLsF0Pi4wPU...&lt;/ds:DigestValue&gt;<br />
                     
&lt;/ds:Reference&gt;<br />
                
&lt;/ds:SignedInfo&gt;   
<br />
                
&lt;ds:SignatureValue&gt;DJbchm5gK...&lt;/ds:SignatureValue&gt; 
<br />
                
&lt;ds:KeyInfo&gt;  
<br />
                 
&lt;wsse:SecurityTokenReference&gt;  
<br />
                   
&lt;wsse:Reference URI="#MyID"/&gt; 
<br />
                  
&lt;/wsse:SecurityTokenReference&gt; 
<br />
              
&lt;/ds:KeyInfo&gt; 
<br />
             &lt;/ds:Signature&gt;<br />
         &lt;/wsse:Security&gt;<br />
         &lt;app:ResponseFormat&gt;Xml&lt;/app:ResponseFormat&gt;<br />
         &lt;app:Key wsu:Id=”AppKey”&gt;27729912882….&lt;/app:Key&gt; 
<br />
    &lt;soap:Header&gt;<br />
    &lt;soap:Body wsu:Id=”MyId”&gt;<br />
          &lt;app:status&gt;Hello, I’m
good&lt;/app:status&gt;<br />
     &lt;/soap:Body&gt;<br />
&lt;/soap:Envelope&gt; </font>
        </p>
        <p>
Not a very pretty song, I’ll admit. Let’s drop a some stuff. Let’s assume that we
don’t need to tell the other party that we’re looking to give it an MD5 signature,
but let’s say that’s implied and so were the canonicalization algorithm. Let’s also
assume that the other side already knows the security token and the key. Since we
only have a single signature digest here and yield a single signature we can just
collapse to the signature value. Heck, you may not even know about what that all means.
Verse 2:
</p>
        <p>
          <font face="Courier New">&lt;soap:Envelope xmlns:soap=”” xmlns:wsaddr=”” xmlns:wsrm=””
xmlns:wsu=”” xmlns:app=””&gt;<br />
   &lt;soap:Header&gt;<br />
         &lt;addr:Action&gt;http://tempuri.org/1.0/Status.set&lt;/addr:Action&gt;<br />
         &lt;wsrm:Sequence&gt;<br />
              &lt;wsrm:Identifier&gt;urn:session-id&lt;/wsrm:Identifier&gt;<br />
              &lt;wsrm:MessageNumber&gt;5&lt;/wsrm:MessageNumber&gt;<br />
          &lt;/wsrm:Sequence&gt;<br />
          &lt;wsse:Security xmlns:wsse=”…”&gt;<br />
              
&lt;ds:Signature&gt;<br />
                 
&lt;ds:SignatureValue&gt;DJbchm5gK...&lt;/ds:SignatureValue&gt; 
<br />
             &lt;/ds:Signature&gt;<br />
         &lt;/wsse:Security&gt;<br />
         &lt;app:ResponseFormat&gt;Xml&lt;/app:ResponseFormat&gt;<br />
         &lt;app:Key wsu:Id=”AppKey”&gt;27729912882….&lt;/app:Key&gt; 
<br />
    &lt;soap:Header&gt;<br />
    &lt;soap:Body wsu:Id=”MyId”&gt;<br />
          &lt;app:status&gt;Hello, I’m
good&lt;/app:status&gt;<br />
     &lt;/soap:Body&gt;<br />
&lt;/soap:Envelope&gt; </font>
        </p>
        <p>
Better. Now let’s strip all these extra XML namespace decorations since there aren’t
any name collisions as far as I can see. We’ll also collapse the rest of the security
elements into one element since there’s no need for three levels of nesting with a
single signature. Verse 3:
</p>
        <p>
          <font face="Courier New">&lt;Envelope&gt;<br />
   &lt;Header&gt;<br />
         &lt;Action&gt;http://tempuri.org/1.0/Status.set&lt;/Action&gt;<br />
         &lt;Sequence&gt;<br />
              &lt;Identifier&gt;urn:session-id&lt;/Identifier&gt;<br />
              &lt;MessageNumber&gt;5&lt;/MessageNumber&gt;<br />
          &lt;/Sequence&gt;<br />
          &lt;SignatureValue&gt;DJbchm5gK...&lt;/SignatureValue&gt;<br />
          &lt;ResponseFormat&gt;Xml&lt;/ResponseFormat&gt;<br />
          &lt;Key&gt;27729912882….&lt;/Key&gt; 
<br />
    &lt;Header&gt;<br />
    &lt;Body&gt;<br />
       &lt;status&gt;Hello, I’m good&lt;/status&gt;<br />
     &lt;/Body&gt;<br />
&lt;/Envelope&gt; </font>
        </p>
        <p>
Much better. The whole angle-bracket stuff and the nesting seems semi-gratuitous and
repetitive here, too. Let’s make that a bit simpler. Verse 4:
</p>
        <p>
          <font face="Courier New">         Action=http://tempuri.org/1.0/Status.set<br />
         Sequence-Identifier=urn:session-id<br />
         Sequence-MessageNumber=5<br />
         SignatureValue=DJbchm5gK...<br />
         ResponseFormat=Xml<br />
         Key=27729912882…. 
<br />
         status=Hello, I’m good</font>
        </p>
        <p>
Much, much better. Now let’s get rid of that weird URI up there and split up the action
and the version info, make some of these keys are little more terse and turn that
into a format that’s easily transmittable over HTTP. By what we have here application/www-form-urlencoded
would probably be best. Verse 5:
</p>
        <p>
          <font face="Courier New">         method=Status.set<br />
         &amp;v=1.0<br />
         &amp;session_key=929872172..<br />
         &amp;call_id=5<br />
         &amp;sig=DJbchm5gK...<br />
         &amp;format=Xml<br />
         &amp;api_key=27729912882…. 
<br />
         &amp;status=Hello,%20I’m%20good</font>
        </p>
        <p>
Oops. <a href="http://wiki.developers.facebook.com/index.php/Status.set">Facebook</a>’s
Status.set API. How did that happen? I thought that was REST?
</p>
        <p>
Now play the song backwards. The “new thing” is largely analogous to where we started
before the WS* Web Services stack and its CORBA/DCE/DCOM predecessors came around
and there are, believe it or not, good reasons for having of that additional “overhead”.
A common way to frame message content and the related control data, a common way to
express complex data structures and distinguish between data domains, a common way
to deal with addressing in multi-hop or store-and-forward messaging scenarios, an
agreed notion of sessions and message sequencing, a solid mechanism for protecting
the integrity of messages and parts of messages. This isn’t all just stupid.
</p>
        <p>
It’s well worth discussing whether messages need to be expressed as XML 1.0 text on
the wire at all times. I don’t think they need to and there are alternatives that
aren’t as heavy. JSON is fine and encodings like the .NET Binary Encoding or Fast
Infoset are viable alternatives as well. It’s also well worth discussing whether WS-Security
and the myriad of related standards that were clearly built by security geniuses for
security geniuses really need to be that complicated or whether we could all live
with a handful of simple profiles and just cut out 80% of the options and knobs and
parameters in that land. 
</p>
        <p>
I find it very sad that the discussion isn’t happening. Instead, people use the “REST”
moniker as the escape hatch to conveniently ignore any existing open standard for
tunnel-through-HTTP messaging and completely avoid the discussion. 
</p>
        <p>
It’s not only sad, it’s actually a bit frustrating. As one of the people responsible
for the protocol surface of the .NET Service Bus, I am absolutely not at liberty to
ignore what exists in the standards space. And this isn’t a mandate handed down to
me, but something I do because I believe it’s the right thing to live with the constraints
of the standards frameworks that exist. 
</p>
        <p>
When we’re sitting down and talk about a REST API, were designing a set of resources
– which may result in splitting a thing like a queue into two resources, head and
tail - and then we put RFC2616 on the table and try to be very precise in picking
the appropriate predefined HTTP method for a given semantic and how the HTTP 2xx,
3xx, 4xx, 5xx status codes map to success and error conditions. We’re also trying
to avoid inventing new ways to express things for which standards exists. There’s
a standard for how to express and manage lists with ATOM and APP and hence we use
that as a foundation. We use the designed extension points to add data to those lists
whenever necessary.
</p>
        <p>
When we’re designing a <strike>RPC</strike> SOAP API, we’re intentionally trying to
avoid inventing new protocol surface and will try to leverage as much from the existing
and standardized stack as we possibly can – at a minimum we’ll stick with established
patterns such as the Create/GetInfo/Renew/Delete patterns for endpoint factories with
renewal (which is used in several standards). I’ll add that we are – ironically -
a bit backlogged on the protocol documentation for our SOAP endpoints and have more
info on the REST endpoint in the latest SDK, but we’ll make that up in the near future.
</p>
        <p>
So - can I build “REST” (mind the quotes) protocols that are as reduced as Facebook,
Twitter, Flickr, etc? Absolutely. There wouldn’t be much new work. It’s just a matter
of how we put messages on and pluck message off the wire. It’s really mostly a matter
of formatting and we have a lot of the necessary building blocks in the shipping WCF
bits today. I would just omit a bunch of decoration as things go out and make a bunch
of assumptions on things that come in.
</p>
        <p>
I just have a sense that I’d be hung upside down from a tree by the press and the
blogging, twittering, facebooking community if I, as someone at Microsoft, wouldn’t
follow the existing open and agreed standards or at least use protocols that we’ve
published under the <a href="http://www.microsoft.com/interop/osp/default.mspx">OSP</a> and
instead just started to do my own interpretative dance - even if that looked strikingly
similar to what the folks down in the Valley are doing. At the very least, someone
would call it a rip-off.
</p>
        <p>
What do you think? What should I/we do? 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=634b72d9-e200-45de-82db-2ae4c8ef947e" />
      </body>
      <title>[Intermission] Auf der Mauer, auf der Lauer sitzt 'ne kleine Wa! - or: When REST isn't REST - or: Why and How I Care About Standards-Compliance</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,634b72d9-e200-45de-82db-2ae4c8ef947e.aspx</guid>
      <link>http://vasters.com/clemensv/2009/04/01/Intermission+Auf+Der+Mauer+Auf+Der+Lauer+Sitzt+Ne+Kleine+Wa+Or+When+REST+Isnt+REST+Or+Why+And+How+I+Care+About+StandardsCompliance.aspx</link>
      <pubDate>Wed, 01 Apr 2009 17:40:41 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;… &lt;a href="http://de.wikipedia.org/wiki/Auf_der_Mauer,_auf_der_Lauer"&gt;seht Euch
mal die Wa an, wie die Wa ta kann. Auf der Mauer auf der Lauer sitzt ‘ne kleine Wa!&lt;/a&gt;.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
It’s a German children’s song. The song starts out with “… sitzt ‘ne kleine Wanze”
(bedbug) and with each verse you leave off a letter: Wanz, Wan, Wa, W, – silence. 
&lt;/p&gt;
&lt;p&gt;
I’ll do the same here, but not with a bedbug:
&lt;/p&gt;
&lt;p&gt;
Let’s sing:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;soap:Envelope xmlns:soap=”” xmlns:wsaddr=”” xmlns:wsrm=””
xmlns:wsu=”” xmlns:app=””&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;soap:Header&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;addr:Action&amp;gt;http://tempuri.org/1.0/Status.set&amp;lt;/addr:Action&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;wsrm:Sequence&amp;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;lt;wsrm:Identifier&amp;gt;urn:session-id&amp;lt;/wsrm:Identifier&amp;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;lt;wsrm:MessageNumber&amp;gt;5&amp;lt;/wsrm:MessageNumber&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/wsrm:Sequence&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;wsse:Security xmlns:wsse=”…”&amp;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;lt;wsse:BinarySecurityToken ValueType="&lt;/font&gt;&lt;font face="Courier New"&gt;http://tempuri.org#CustomToken&lt;/font&gt;&lt;font face="Courier New"&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;&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;
EncodingType="...#Base64Binary" wsu:Id=" MyID "&amp;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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
FHUIORv...&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;lt;/wsse:BinarySecurityToken&amp;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;lt;ds:Signature&amp;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;lt;ds:SignedInfo&amp;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;&amp;nbsp;&amp;nbsp;
&amp;lt;ds:CanonicalizationMethod Algorithm="&lt;/font&gt;&lt;font face="Courier New"&gt;http://www.w3.org/2001/10/xml-exc-c14n#"/&amp;gt;&lt;/font&gt;
&lt;br&gt;
&lt;font face="Courier New"&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;lt;ds:SignatureMethod Algorithm="&lt;/font&gt;&lt;font face="Courier New"&gt;http://www.w3.org/2000/09/xmldsig#md5"/&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;ds:Reference URI="#MsgBody"&amp;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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;ds:DigestMethod&amp;nbsp; Algorithm="&lt;/font&gt;&lt;font face="Courier New"&gt;http://www.w3.org/2000/09/xmldsig#md5"/&amp;gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&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;&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;lt;ds:DigestValue&amp;gt;LyLsF0Pi4wPU...&amp;lt;/ds:DigestValue&amp;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;&amp;nbsp;&amp;nbsp;
&amp;lt;/ds:Reference&amp;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;lt;/ds:SignedInfo&amp;gt;&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;&amp;nbsp;
&amp;lt;ds:SignatureValue&amp;gt;DJbchm5gK...&amp;lt;/ds:SignatureValue&amp;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;lt;ds:KeyInfo&amp;gt;&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;&amp;nbsp;&amp;nbsp;
&amp;lt;wsse:SecurityTokenReference&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;wsse:Reference URI="#MyID"/&amp;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;lt;/wsse:SecurityTokenReference&amp;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;lt;/ds:KeyInfo&amp;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;lt;/ds:Signature&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/wsse:Security&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;app:ResponseFormat&amp;gt;Xml&amp;lt;/app:ResponseFormat&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;app:Key wsu:Id=”AppKey”&amp;gt;27729912882….&amp;lt;/app:Key&amp;gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;soap:Header&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;soap:Body wsu:Id=”MyId”&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;app:status&amp;gt;Hello, I’m
good&amp;lt;/app:status&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/soap:Body&amp;gt;&lt;br&gt;
&amp;lt;/soap:Envelope&amp;gt; &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Not a very pretty song, I’ll admit. Let’s drop a some stuff. Let’s assume that we
don’t need to tell the other party that we’re looking to give it an MD5 signature,
but let’s say that’s implied and so were the canonicalization algorithm. Let’s also
assume that the other side already knows the security token and the key. Since we
only have a single signature digest here and yield a single signature we can just
collapse to the signature value. Heck, you may not even know about what that all means.
Verse 2:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;soap:Envelope xmlns:soap=”” xmlns:wsaddr=”” xmlns:wsrm=””
xmlns:wsu=”” xmlns:app=””&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;soap:Header&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;addr:Action&amp;gt;http://tempuri.org/1.0/Status.set&amp;lt;/addr:Action&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;wsrm:Sequence&amp;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;lt;wsrm:Identifier&amp;gt;urn:session-id&amp;lt;/wsrm:Identifier&amp;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;lt;wsrm:MessageNumber&amp;gt;5&amp;lt;/wsrm:MessageNumber&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/wsrm:Sequence&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;wsse:Security xmlns:wsse=”…”&amp;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;lt;ds:Signature&amp;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;lt;ds:SignatureValue&amp;gt;DJbchm5gK...&amp;lt;/ds:SignatureValue&amp;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;lt;/ds:Signature&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/wsse:Security&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;app:ResponseFormat&amp;gt;Xml&amp;lt;/app:ResponseFormat&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;app:Key wsu:Id=”AppKey”&amp;gt;27729912882….&amp;lt;/app:Key&amp;gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;soap:Header&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;soap:Body wsu:Id=”MyId”&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;app:status&amp;gt;Hello, I’m
good&amp;lt;/app:status&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/soap:Body&amp;gt;&lt;br&gt;
&amp;lt;/soap:Envelope&amp;gt; &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Better. Now let’s strip all these extra XML namespace decorations since there aren’t
any name collisions as far as I can see. We’ll also collapse the rest of the security
elements into one element since there’s no need for three levels of nesting with a
single signature. Verse 3:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;Envelope&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;Header&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Action&amp;gt;http://tempuri.org/1.0/Status.set&amp;lt;/Action&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Sequence&amp;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;lt;Identifier&amp;gt;urn:session-id&amp;lt;/Identifier&amp;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;lt;MessageNumber&amp;gt;5&amp;lt;/MessageNumber&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Sequence&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SignatureValue&amp;gt;DJbchm5gK...&amp;lt;/SignatureValue&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ResponseFormat&amp;gt;Xml&amp;lt;/ResponseFormat&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Key&amp;gt;27729912882….&amp;lt;/Key&amp;gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Header&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Body&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;status&amp;gt;Hello, I’m good&amp;lt;/status&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Body&amp;gt;&lt;br&gt;
&amp;lt;/Envelope&amp;gt; &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Much better. The whole angle-bracket stuff and the nesting seems semi-gratuitous and
repetitive here, too. Let’s make that a bit simpler. Verse 4:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Action=http://tempuri.org/1.0/Status.set&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sequence-Identifier=urn:session-id&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sequence-MessageNumber=5&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SignatureValue=DJbchm5gK...&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResponseFormat=Xml&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Key=27729912882…. 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; status=Hello, I’m good&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Much, much better. Now let’s get rid of that weird URI up there and split up the action
and the version info, make some of these keys are little more terse and turn that
into a format that’s easily transmittable over HTTP. By what we have here application/www-form-urlencoded
would probably be best. Verse 5:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; method=Status.set&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;v=1.0&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;session_key=929872172..&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;call_id=5&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;sig=DJbchm5gK...&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;format=Xml&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;api_key=27729912882…. 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;status=Hello,%20I’m%20good&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Oops. &lt;a href="http://wiki.developers.facebook.com/index.php/Status.set"&gt;Facebook&lt;/a&gt;’s
Status.set API. How did that happen? I thought that was REST?
&lt;/p&gt;
&lt;p&gt;
Now play the song backwards. The “new thing” is largely analogous to where we started
before the WS* Web Services stack and its CORBA/DCE/DCOM predecessors came around
and there are, believe it or not, good reasons for having of that additional “overhead”.
A common way to frame message content and the related control data, a common way to
express complex data structures and distinguish between data domains, a common way
to deal with addressing in multi-hop or store-and-forward messaging scenarios, an
agreed notion of sessions and message sequencing, a solid mechanism for protecting
the integrity of messages and parts of messages. This isn’t all just stupid.
&lt;/p&gt;
&lt;p&gt;
It’s well worth discussing whether messages need to be expressed as XML 1.0 text on
the wire at all times. I don’t think they need to and there are alternatives that
aren’t as heavy. JSON is fine and encodings like the .NET Binary Encoding or Fast
Infoset are viable alternatives as well. It’s also well worth discussing whether WS-Security
and the myriad of related standards that were clearly built by security geniuses for
security geniuses really need to be that complicated or whether we could all live
with a handful of simple profiles and just cut out 80% of the options and knobs and
parameters in that land. 
&lt;/p&gt;
&lt;p&gt;
I find it very sad that the discussion isn’t happening. Instead, people use the “REST”
moniker as the escape hatch to conveniently ignore any existing open standard for
tunnel-through-HTTP messaging and completely avoid the discussion. 
&lt;/p&gt;
&lt;p&gt;
It’s not only sad, it’s actually a bit frustrating. As one of the people responsible
for the protocol surface of the .NET Service Bus, I am absolutely not at liberty to
ignore what exists in the standards space. And this isn’t a mandate handed down to
me, but something I do because I believe it’s the right thing to live with the constraints
of the standards frameworks that exist. 
&lt;/p&gt;
&lt;p&gt;
When we’re sitting down and talk about a REST API, were designing a set of resources
– which may result in splitting a thing like a queue into two resources, head and
tail - and then we put RFC2616 on the table and try to be very precise in picking
the appropriate predefined HTTP method for a given semantic and how the HTTP 2xx,
3xx, 4xx, 5xx status codes map to success and error conditions. We’re also trying
to avoid inventing new ways to express things for which standards exists. There’s
a standard for how to express and manage lists with ATOM and APP and hence we use
that as a foundation. We use the designed extension points to add data to those lists
whenever necessary.
&lt;/p&gt;
&lt;p&gt;
When we’re designing a &lt;strike&gt;RPC&lt;/strike&gt; SOAP API, we’re intentionally trying to
avoid inventing new protocol surface and will try to leverage as much from the existing
and standardized stack as we possibly can – at a minimum we’ll stick with established
patterns such as the Create/GetInfo/Renew/Delete patterns for endpoint factories with
renewal (which is used in several standards). I’ll add that we are – ironically -
a bit backlogged on the protocol documentation for our SOAP endpoints and have more
info on the REST endpoint in the latest SDK, but we’ll make that up in the near future.
&lt;/p&gt;
&lt;p&gt;
So - can I build “REST” (mind the quotes) protocols that are as reduced as Facebook,
Twitter, Flickr, etc? Absolutely. There wouldn’t be much new work. It’s just a matter
of how we put messages on and pluck message off the wire. It’s really mostly a matter
of formatting and we have a lot of the necessary building blocks in the shipping WCF
bits today. I would just omit a bunch of decoration as things go out and make a bunch
of assumptions on things that come in.
&lt;/p&gt;
&lt;p&gt;
I just have a sense that I’d be hung upside down from a tree by the press and the
blogging, twittering, facebooking community if I, as someone at Microsoft, wouldn’t
follow the existing open and agreed standards or at least use protocols that we’ve
published under the &lt;a href="http://www.microsoft.com/interop/osp/default.mspx"&gt;OSP&lt;/a&gt; and
instead just started to do my own interpretative dance - even if that looked strikingly
similar to what the folks down in the Valley are doing. At the very least, someone
would call it a rip-off.
&lt;/p&gt;
&lt;p&gt;
What do you think? What should I/we do? 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=634b72d9-e200-45de-82db-2ae4c8ef947e" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,634b72d9-e200-45de-82db-2ae4c8ef947e.aspx</comments>
      <category>.NET Services</category>
      <category>Architecture</category>
      <category>Azure</category>
      <category>Technology</category>
      <category>Technology/ISB</category>
      <category>Technology/Web Services</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=017e2771-fd13-4a3e-97a3-d1a8dcc8c104</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,017e2771-fd13-4a3e-97a3-d1a8dcc8c104.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,017e2771-fd13-4a3e-97a3-d1a8dcc8c104.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=017e2771-fd13-4a3e-97a3-d1a8dcc8c104</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Didn't I write that I wanted to blog more this year? It's June, you see what came
out of that. 
</p>
        <p>
First things, first; I'm flying to Orlando tomorrow for TechEd. Looking back at what
my conference schedule looked like up until 2 years ago, it's hard to believe that
this is my first (!) scheduled conference talk this year. I actually do miss the life
on the road a little bit. The compensation for it is that I get to see my family every
day (my daughter Eva's first birthday is coming up on June 25th) and that I'm getting
to work on and define the stuff that I 'just' used to be talking about. This
really is the first time that I do a talk about a Microsoft technology that I own;
so that's a bit of a thing:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <strong>SOA 403 </strong>
            <a class="txtbutton" onclick="doEdit('c735bf60-6940-4857-b38f-228345702281')">
              <strong>Building
Federated Solutions on the Internet Service Bus</strong>
            </a>
            <br />
Thursday, June 5, 2008 10:15AM-11:30AM<br />
Room: S220 C (DEV) 
</p>
        </blockquote>
        <p>
'Own' means here that I'm the responsible Program Manager for the entire 'Messaging'
feature area of <a href="http://labs.biztalk.net">BizTalk Services</a> in what
we call the '.NET Online Services' team around here. The PM title isn't entirely accurate,
because I'm also writing pretty substantial amounts of product code these days. The
ability to write and contribute code into the product was the primary reason why I
switched jobs and joined the team I'm now in, but it turned out that the PM role
was the overall better fit for me. So I'm 60% PM and 40% Dev. Or something like
that.
</p>
        <p>
Back to TechEd. There are two talk about what we're building. The first
one is 'today' (I'm still on Pacific Time so I realize that may be a bit
late); Justin Smith will provide a broad overview on the services we're building:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <strong>SOA206 Messaging, Identity, and Workflow in the Cloud<br /></strong>Tuesday, June 3 10:30 AM - 11:45 AM<br />
Room: S220 C   
</p>
        </blockquote>
        <div class="catalogSessionStatus" id="statusdf4127b5-d236-4daa-b0d9-5d050b05ed76">
        </div>
        <div class="speakers">The second talk is mine (above) and as you might be able to
tell by the '400' classification I've got the clear intent not to spend too much time
in Powerpoint. I am going to show four common architectural issues and ways to deal
with them using the cloud platform. And I'm going to show you the code for it. I also
plan (we'll see how that part goes with the on-site network) to host an app for 'crowd
participation' so that I'm explicitly not going to ask you to turn your laptops off.
Since the BizTalk Services SDK hasn't spread very broadly, yet, I'll base the majority
of the demos on the SDK samples so that you can easily repro the stuff that I show
you.
</div>
        <div class="speakers"> 
</div>
        <div class="speakers">Now ... you say ... "BizTalk Services? I don't have anything
to do with BizTalk! Do you want to sell me BizTalk Server?" 
</div>
        <div class="speakers"> 
</div>
        <div class="speakers">Well, it's always nice if customers decide to pick
up some BizTalk Server licenses, but: No, I don't. Our stuff does actually compose
with BizTalk Server 2006 R2 through the WCF Adapter, but the way to think about
this <strong>code-name </strong>is that 'BizTalk' just happens to be the brand
that our division has been using for Messaging. There was the BizTalk Framework, BizTalk
Server and now we've got BizTalk Services. It's a brand. And we're actually finding
that that name isn't really a perfect fit for what we're doing; customers suggest
the same. So there'll be a different name. I'm guessing we're going to talk about
that new name and some other cards we hold in our hands at or around <a href="http://microsoftpdc.com/">PDC</a>.
</div>
        <div class="speakers"> 
</div>
        <div class="speakers">The stuff that I own in the 'Cloud' Messaging area are Naming,
Service Registry, Connectivity/NAT Traversal, Relay, Eventing, a bunch of internal,
servide-side infrastructure supporting those feature areas and some feature areas
that we'll talk about more at PDC. So the fun part of TechEd for me (and you) is that
the 'feedback opportunity' is pretty immediate. We're updating the services (just
about) every quarter and I'll probably check in my last set of stuff for the
current release cycle from Orlando or the night I get back here. From there I'm switching
into planning mode for the next release (aligned with PDC) and if you bring good ideas
that we can fit into the next cycle, I'm very inclined to take them. Not that we'd
have any shortage of feature ideas, mind you. More is better.
</div>
        <div class="speakers"> 
</div>
        <div class="speakers">If you are in Orlando .. I'll have booth duty at the WCF
booth in the Exhibition Hall (or whatever they call it this year) both Wednesday and
Thursday from 2:30PM to closing so come see me there or come to see my talk or just
grab me at the Attendee Party if you can recognize me. ;-)
</div>
        <div class="speakers"> 
</div>
        <div class="speakers">If you are not: <a href="http://labs.biztalk.net">http://labs.biztalk.net</a>  
</div>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=017e2771-fd13-4a3e-97a3-d1a8dcc8c104" />
      </body>
      <title>TechEd Time!  - and what I'm up to these days</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,017e2771-fd13-4a3e-97a3-d1a8dcc8c104.aspx</guid>
      <link>http://vasters.com/clemensv/2008/06/03/TechEd+Time+And+What+Im+Up+To+These+Days.aspx</link>
      <pubDate>Tue, 03 Jun 2008 06:47:12 GMT</pubDate>
      <description>&lt;p&gt;
Didn't I write that I wanted to blog more this year? It's June, you see what came
out of that. 
&lt;/p&gt;
&lt;p&gt;
First things, first; I'm flying to Orlando tomorrow for TechEd. Looking back at what
my conference schedule looked like up until 2 years ago, it's hard to believe that
this is my first (!) scheduled conference talk this year. I actually do miss the life
on the road a little bit. The compensation for it is that I get to see my family every
day (my daughter Eva's first birthday is coming up on June 25th) and that I'm getting
to work on and define the stuff that I&amp;nbsp;'just' used to be talking about. This
really is the first time that I do a talk about a Microsoft technology that I own;
so that's a bit of a thing:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;strong&gt;SOA 403 &lt;/strong&gt;&lt;a class=txtbutton onclick="doEdit('c735bf60-6940-4857-b38f-228345702281')"&gt;&lt;strong&gt;Building
Federated Solutions on the Internet Service Bus&lt;/strong&gt;&lt;/a&gt; 
&lt;br&gt;
Thursday, June&amp;nbsp;5, 2008 10:15AM-11:30AM&lt;br&gt;
Room: S220 C (DEV) 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
'Own' means here that I'm the responsible Program Manager for the entire 'Messaging'
feature area of &lt;a href="http://labs.biztalk.net"&gt;BizTalk Services&lt;/a&gt;&amp;nbsp;in what
we call the '.NET Online Services' team around here. The PM title isn't entirely accurate,
because I'm also writing pretty substantial amounts of product code these days. The
ability to write and contribute code into the product was the primary reason why I
switched jobs&amp;nbsp;and joined the team I'm now in, but it turned out that the PM role
was the overall better fit for&amp;nbsp;me. So I'm 60% PM and 40% Dev. Or something like
that.
&lt;/p&gt;
&lt;p&gt;
Back to TechEd.&amp;nbsp;There are two talk about&amp;nbsp;what we're building. The first
one is&amp;nbsp;'today' (I'm&amp;nbsp;still on Pacific Time so I realize that may be a bit
late); Justin Smith will provide a broad overview on the services we're building:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;strong&gt;SOA206 Messaging, Identity, and Workflow in the Cloud&lt;br&gt;
&lt;/strong&gt;Tuesday, June 3 10:30 AM - 11:45 AM&lt;br&gt;
Room: S220 C &amp;nbsp; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;div class=catalogSessionStatus id=statusdf4127b5-d236-4daa-b0d9-5d050b05ed76&gt;
&lt;/div&gt;
&lt;div class=speakers&gt;The second talk is mine (above) and as you might be able to tell
by the '400' classification I've got the clear intent not to spend too much time in
Powerpoint. I am going to show four common architectural issues and ways to deal with
them using the cloud platform. And I'm going to show you the code for it. I also plan
(we'll see how that part goes with the on-site network) to host an app for 'crowd
participation' so that I'm explicitly not going to ask you to turn your laptops off.
Since the BizTalk Services SDK hasn't spread very broadly, yet, I'll base the majority
of the demos on the SDK samples so that you can easily repro the stuff that I show
you.
&lt;/div&gt;
&lt;div class=speakers&gt;&amp;nbsp;
&lt;/div&gt;
&lt;div class=speakers&gt;Now ... you say ... "BizTalk Services? I don't have anything to
do with BizTalk! Do you want to sell me&amp;nbsp;BizTalk Server?"&amp;nbsp;
&lt;/div&gt;
&lt;div class=speakers&gt;&amp;nbsp;
&lt;/div&gt;
&lt;div class=speakers&gt;Well, it's always nice if customers&amp;nbsp;decide to&amp;nbsp;pick up
some BizTalk Server licenses, but: No, I don't.&amp;nbsp;Our stuff does actually compose
with BizTalk Server 2006 R2 through the WCF&amp;nbsp;Adapter, but the way to think about
this &lt;strong&gt;code-name&amp;nbsp;&lt;/strong&gt;is that 'BizTalk' just happens to be the brand
that our division has been using for Messaging. There was the BizTalk Framework, BizTalk
Server and now we've got BizTalk Services. It's a brand. And we're actually finding
that that name isn't really a perfect fit for what we're doing; customers suggest
the same. So there'll be a different name. I'm guessing we're going to talk about
that new name and some other cards we hold&amp;nbsp;in our&amp;nbsp;hands at or around &lt;a href="http://microsoftpdc.com/"&gt;PDC&lt;/a&gt;.
&lt;/div&gt;
&lt;div class=speakers&gt;&amp;nbsp;
&lt;/div&gt;
&lt;div class=speakers&gt;The stuff that I own in the 'Cloud' Messaging area are Naming,
Service Registry, Connectivity/NAT Traversal, Relay, Eventing, a bunch of internal,
servide-side infrastructure supporting those feature areas and some feature areas
that we'll talk about more at PDC. So the fun part of TechEd for me (and you) is that
the 'feedback opportunity' is pretty immediate. We're updating the services (just
about) every quarter and I'll probably check in my last set of&amp;nbsp;stuff for the
current release cycle from Orlando or the night I get back here. From there I'm switching
into planning mode for the next release (aligned with PDC) and if you bring good ideas
that we can fit into the next cycle, I'm very inclined to take them. Not that we'd
have any shortage of feature ideas, mind you. More is better.
&lt;/div&gt;
&lt;div class=speakers&gt;&amp;nbsp;
&lt;/div&gt;
&lt;div class=speakers&gt;If you are in Orlando ..&amp;nbsp;I'll have booth duty at the WCF
booth in the Exhibition Hall (or whatever they call it this year) both Wednesday and
Thursday from 2:30PM to closing so come see me there or come to see my talk or just
grab me at the Attendee Party if you&amp;nbsp;can recognize me.&amp;nbsp;;-)
&lt;/div&gt;
&lt;div class=speakers&gt;&amp;nbsp;
&lt;/div&gt;
&lt;div class=speakers&gt;If you are not: &lt;a href="http://labs.biztalk.net"&gt;http://labs.biztalk.net&lt;/a&gt; &amp;nbsp;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=017e2771-fd13-4a3e-97a3-d1a8dcc8c104" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,017e2771-fd13-4a3e-97a3-d1a8dcc8c104.aspx</comments>
      <category>Architecture</category>
      <category>Talks/TechEd US</category>
      <category>Technology/ISB</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=798bbf5b-f9f9-45b9-87ba-f6a30c359af9</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,798bbf5b-f9f9-45b9-87ba-f6a30c359af9.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,798bbf5b-f9f9-45b9-87ba-f6a30c359af9.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=798bbf5b-f9f9-45b9-87ba-f6a30c359af9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p align="justify">
A flock of pigs has been doing aerobatics high up over Microsoft Campus in Redmond
in the past three weeks. Neither City of Redmond nor Microsoft spokespeople returned
calls requesting comments in time for this article. An Microsoft worker who requested
anonymity and has seen the pigs flying overhead commented that "they are as good as
the Blue Angels at Seafair, just funnier" and "they seem to circle over building 42
a lot, but I wouldn't know why". 
</p>
        <p>
In related news ... 
</p>
        <p align="justify">
We wrapped up the BizTalk Services "R11" CTP this last Thursday and put the latest
SDK release up on <a href="http://labs.biztalk.net/">http://labs.biztalk.net/</a>.
As you may or may not know, "BizTalk Services" is the codename for Microsoft's cloud-based
Identity and Connectivity services - with a significant set of further services in
the pipeline. The R11 release is a major milestone for the data center side of BizTalk
Services, but we've also added several new client-facing features, especially on the
Identity services. You can now authenticate using a certificate in addition to username
and CardSpace authentication, we have enabled support for 3rd party managed CardSpace
cards, and there is extended support for claims based authorization. 
</p>
        <p>
Now the surprising bit:
</p>
        <p align="justify">
Only about an hour before we locked down the SDK on Thursday, we checked a sample
into the samples tree that has a rather unusual set of prerequisites for something
coming out of Microsoft: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p align="justify">
Runtime: <a href="http://java.sun.com/javaee/">Java EE 5</a> on <a href="https://glassfish.dev.java.net/">Sun
Glassfish v2</a> + <a href="https://metro.dev.java.net/">Sun WSIT/Metro</a> (JAX-WS
extensions), Tool: <a href="http://netbeans.org">Netbeans 6.0 IDE</a>. 
</p>
        </blockquote>
        <p align="justify">
The sample shows how to use the BizTalk Services Identity Security Token Service (STS)
to secure the communication between a Java client and a Java service providing federated
authentication and claims-based authorization.
</p>
        <p align="justify">
The sample, which you can find in <em>./Samples/OtherPlatforms/StandaloneAccessControl/JavaEE5</em> once
you installed the SDK, is a pure Java sample not requiring any of our bits on either
the service or client side. The interaction with our services is purely happening
on the wire. 
</p>
        <p align="justify">
If you are a "Javahead", it might seem odd that we're shipping this sample inside
a Windows-only MSI installer and I will agree that that's odd. It's simply a function
of timing and the point in time when we knew that we could get it done (some more
on that below). For the next BizTalk Services SDK release I expect there to be an
additional .jar file for the Java samples.
</p>
        <p align="justify">
It's important to note that this isn't just a thing we did as a one-time thing and
because we could. We have done a significant amount of work on the backend protocol
implementations to start opening up a very broad set of scenarios on the BizTalk Services
Connectivity services for platforms other than .NET. We already have a set of additional
Java EE samples lined up for when we enable that functionality on the backend. However,
since getting security and identity working is a prerequisite for making all other
services work, that's where we started. There'll be more and there'll be more platform
and language choice than Java down the road. 
</p>
        <p align="justify">
Just to be perfectly clear: Around here we strongly believe that .NET and the Windows
Communication Foundation in particular is the most advanced platform to build services,
irrespective of whether they are of the WS-* or REST variety. If you care about my
personal opinion, I'll say that several months of research into the capabilities of
other platforms has only reaffirmed that belief for me and I don't even need to put
a Microsoft hat on to say that. 
</p>
        <p align="justify">
But we recognize and respect that there are a great variety of individual reasons
why people might not be using .NET and WCF. The obvious one is "platform". If you
run on Linux or Unix and/or if your deployment target is a Java Application Server,
then your platform is very likely not .NET. It's something else. If that's your
world, we still think that our services are something that's useful for your applications
and we want to show you why. And it is absolutely not enough for us to say "here is
the wire protocol documentation; go party!". Only Code is Truth.
</p>
        <p align="justify">
I'm also writing "Only Code is Truth" also because we've found - perhaps not too surprisingly
- that there is a significant difference between reading and implementing the WS-*
specs and having things actually work. And here I get to the point where a round of
public "Thank You" is due:
</p>
        <p align="justify">
The Metro team over at Sun Microsystems has made a very significant contribution to
making this all work. Before we started making changes to accommodate Java, there
would have been very little hope for anyone to get this seemingly simple
scenario to work. We had to make quite a few changes even though our service did follow
the specs. 
</p>
        <p align="justify">
While we were adjusting our backend STS accordingly, the Sun Metro team worked on
a set of issues that we identified on their end (with fantastic turnaround times)
and worked those into their public nightly builds. The Sun team also 'promoted' a
nightly build of Metro 1.2 to a semi-permanent <a href="https://metro.dev.java.net/servlets/ProjectDocumentList?folderID=8958&amp;expandFolder=8958&amp;folderID=7636">download
location</a> (the first 1.2 build that got that treatment), because it is the build
tested to successfully interop with our SDK release, even though that build is known
to have some regressions for some of their other test scenarios. As they work towards
wrapping up their 1.2 release and fix those other bugs, we’ll continue to test and
talk to help that the interop scenarios keep working. 
</p>
        <p align="justify">
As a result of this collaboration, Metro 1.2 is going to be a better and more interoperable
release for the Sun's customers and the greater Java community and BizTalk Services
as well as our future identity products will be better and more interoperable, too.
Win-Win. Thank you, Sun.
</p>
        <p align="justify">
As a goodie, I put some code into the Java sample that might be useful even if you
don't even care about our services. Since configuring the Java certificate stores
for standalone applications can be really painful, I added some simple code that's
using a week-old feature of the latest Metro 1.2 bits that allows configuring the
Truststores/Keystores dynamically and pull the stores from the client's .jar at runtime.
The code also has an authorization utility class that shows how to get and evaluate
claims on the service side by pulling the SAML token out of the context and pulling
the correct attributes from the token.
</p>
        <p>
Have fun.
</p>
        <p>
[By the way, this is not an April Fool's joke, in case you were wondering]<br /></p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=798bbf5b-f9f9-45b9-87ba-f6a30c359af9" />
      </body>
      <title>BizTalk Services "R11" CTP Comes with a Surprise</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,798bbf5b-f9f9-45b9-87ba-f6a30c359af9.aspx</guid>
      <link>http://vasters.com/clemensv/2008/03/31/BizTalk+Services+R11+CTP+Comes+With+A+Surprise.aspx</link>
      <pubDate>Mon, 31 Mar 2008 17:56:40 GMT</pubDate>
      <description>&lt;p align=justify&gt;
A flock of pigs has been doing aerobatics high up over Microsoft Campus in Redmond
in the past three weeks. Neither City of Redmond nor Microsoft spokespeople returned
calls requesting comments in time for this article. An Microsoft worker who requested
anonymity and has seen the pigs flying overhead commented that "they are as good as
the Blue Angels at Seafair, just funnier" and "they seem to circle over building 42
a lot, but I wouldn't know why". 
&lt;/p&gt;
&lt;p&gt;
In related news ... 
&lt;/p&gt;
&lt;p align=justify&gt;
We wrapped up the BizTalk Services "R11" CTP this last Thursday and put the latest
SDK release up on &lt;a href="http://labs.biztalk.net/"&gt;http://labs.biztalk.net/&lt;/a&gt;.
As you may or may not know, "BizTalk Services" is the codename for Microsoft's cloud-based
Identity and Connectivity services - with a significant set of further services in
the pipeline. The R11 release is a major milestone for the data center side of BizTalk
Services, but we've also added several new client-facing features, especially on the
Identity services. You can now authenticate using a certificate in addition to username
and CardSpace authentication, we have enabled support for 3rd party managed CardSpace
cards, and there is extended support for claims based authorization. 
&lt;/p&gt;
&lt;p&gt;
Now the surprising bit:
&lt;/p&gt;
&lt;p align=justify&gt;
Only about an hour before we locked down the SDK on Thursday, we checked a sample
into the samples tree that has a rather unusual set of prerequisites for something
coming out of Microsoft: 
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p align=justify&gt;
Runtime: &lt;a href="http://java.sun.com/javaee/"&gt;Java EE 5&lt;/a&gt; on &lt;a href="https://glassfish.dev.java.net/"&gt;Sun
Glassfish v2&lt;/a&gt; + &lt;a href="https://metro.dev.java.net/"&gt;Sun WSIT/Metro&lt;/a&gt; (JAX-WS
extensions), Tool: &lt;a href="http://netbeans.org"&gt;Netbeans 6.0 IDE&lt;/a&gt;. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p align=justify&gt;
The sample shows how to use the BizTalk Services Identity Security Token Service (STS)
to secure the communication between a Java client and a Java service providing federated
authentication and claims-based authorization.
&lt;/p&gt;
&lt;p align=justify&gt;
The sample, which you can find in &lt;em&gt;./Samples/OtherPlatforms/StandaloneAccessControl/JavaEE5&lt;/em&gt; once
you installed the SDK, is a pure Java sample not requiring any of our bits on either
the service or client side. The interaction with our services is purely happening
on the wire. 
&lt;/p&gt;
&lt;p align=justify&gt;
If you are a "Javahead", it might seem odd that we're shipping this sample inside
a Windows-only MSI installer and I will agree that that's odd. It's simply a function
of timing and the point in time when we knew that we could get it done (some more
on that below). For the next BizTalk Services SDK release I expect there to be an
additional .jar file for the Java samples.
&lt;/p&gt;
&lt;p align=justify&gt;
It's important to note that this isn't just a thing we did as a one-time thing and
because we could. We have done a significant amount of work on the backend protocol
implementations to start opening up a very broad set of scenarios on the BizTalk Services
Connectivity services for platforms other than .NET. We already have a set of additional
Java EE samples lined up for when we enable that functionality on the backend. However,
since getting security and identity working is a prerequisite for making all other
services work, that's where we started. There'll be more and there'll be more platform
and language choice than Java down the road. 
&lt;/p&gt;
&lt;p align=justify&gt;
Just to be perfectly clear: Around here we strongly believe that .NET and the Windows
Communication Foundation in particular is the most advanced platform to build services,
irrespective of whether they are of the WS-* or REST variety. If you care about my
personal opinion, I'll say that several months of research into the capabilities of
other platforms has only reaffirmed that belief for me and I don't even need to put
a Microsoft hat on to say that. 
&lt;/p&gt;
&lt;p align=justify&gt;
But we recognize and respect that there are a great variety of individual reasons
why people might not be using .NET and WCF. The obvious one is "platform". If you
run on Linux or Unix and/or if your deployment target is a Java Application Server,
then your platform is very likely not .NET. It's something else.&amp;nbsp;If that's your
world, we still think that our services are something that's useful for your applications
and we want to show you why. And it is absolutely not enough for us to say "here is
the wire protocol documentation; go party!". Only Code is Truth.
&lt;/p&gt;
&lt;p align=justify&gt;
I'm also writing "Only Code is Truth" also because we've found - perhaps not too surprisingly
- that there is a significant difference between reading and implementing the WS-*
specs and having things actually work. And here I get to the point where a round of
public "Thank You" is due:
&lt;/p&gt;
&lt;p align=justify&gt;
The Metro team over at Sun Microsystems has made a very significant contribution to
making this all work. Before we started making changes to accommodate Java, there
would have been&amp;nbsp;very little&amp;nbsp;hope for anyone to get this seemingly simple
scenario to work. We had to make quite a few changes even though our service did follow
the specs. 
&lt;/p&gt;
&lt;p align=justify&gt;
While we were adjusting our backend STS accordingly, the Sun Metro team worked on
a set of issues that we identified on their end (with fantastic turnaround times)
and worked those into their public nightly builds. The Sun team also 'promoted' a
nightly build of Metro 1.2 to a semi-permanent &lt;a href="https://metro.dev.java.net/servlets/ProjectDocumentList?folderID=8958&amp;amp;expandFolder=8958&amp;amp;folderID=7636"&gt;download
location&lt;/a&gt; (the first 1.2 build that got that treatment), because it is the build
tested to successfully interop with our SDK release, even though that build is known
to have some regressions for some of their other test scenarios. As they work towards
wrapping up their 1.2 release and fix those other bugs, we’ll continue to test and
talk to help that the interop scenarios keep working. 
&lt;/p&gt;
&lt;p align=justify&gt;
As a result of this collaboration, Metro 1.2 is going to be a better and more interoperable
release for the Sun's customers and the greater Java community and BizTalk Services
as well as our future identity products will be better and more interoperable, too.
Win-Win. Thank you, Sun.
&lt;/p&gt;
&lt;p align=justify&gt;
As a goodie, I put some code into the Java sample that might be useful even if you
don't even care about our services. Since configuring the Java certificate stores
for standalone applications can be really painful, I added some simple code that's
using a week-old feature of the latest Metro 1.2 bits that allows configuring the
Truststores/Keystores dynamically and pull the stores from the client's .jar at runtime.
The code also has an authorization utility class that shows how to get and evaluate
claims on the service side by pulling the SAML token out of the context and pulling
the correct attributes from the token.
&lt;/p&gt;
&lt;p&gt;
Have fun.
&lt;/p&gt;
&lt;p&gt;
[By the way, this is not an April Fool's joke, in case you were wondering]&lt;br&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=798bbf5b-f9f9-45b9-87ba-f6a30c359af9" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,798bbf5b-f9f9-45b9-87ba-f6a30c359af9.aspx</comments>
      <category>Architecture</category>
      <category>IT Strategy</category>
      <category>Technology</category>
      <category>Technology/CardSpace</category>
      <category>Technology/ISB</category>
      <category>Technology/WCF</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=a1692142-3221-4ecc-8e5f-5aff2635d714</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,a1692142-3221-4ecc-8e5f-5aff2635d714.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,a1692142-3221-4ecc-8e5f-5aff2635d714.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=a1692142-3221-4ecc-8e5f-5aff2635d714</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Even though the <a href="http://www.mseventseurope.com/teched/07/developers/Pages/default.aspx">TechEd
Europe Developer Website</a> doesn't yet clearly say so, Steve Swartz and myself will
"of course!" be back with a new set of Steve &amp; Clemens talks in Barcelona for
TechEd Europe Developer (November 5-9). And for the first time we'll stay for another
week and also give a talk at <a href="http://www.mseventseurope.com/teched/07/itforum/Pages/Default.aspx">TechEd
Europe ITForum</a> (November 12-16) this year. 
</p>
        <p>
What will we talk about? 
</p>
        <p>
Last year we've started with a history lesson, did a broad and mostly technology
agnostic overview of distributed systems architecture across 4 talks and
closed with a talk that speculated about the future. 
</p>
        <p>
This year at the TechEd Developer show, we'll be significantly more concrete and zoom
in on the technologies that make up the Microsoft SOA and Business Process platform
and show how things are meant to fit together. We'll talk about the rise of declarative
programming and composition and how that manifests in the .NET Framework and elsewhere.
And as messaging dudes we'll also talk about messaging again. At TechEd ITForum we'll talk
about the end-to-end lifecycle of composite applications and how to manage it effectively.
</p>
        <p>
And of course there'll be "futures". Much less handwavy futures than last year, actually.
</p>
        <p>
So .... We'll be in Barcelona for TechEd. You too?
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=a1692142-3221-4ecc-8e5f-5aff2635d714" />
      </body>
      <title>Live again at TechEd Barcelona: The Steve &amp; Clemens Show </title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,a1692142-3221-4ecc-8e5f-5aff2635d714.aspx</guid>
      <link>http://vasters.com/clemensv/2007/08/29/Live+Again+At+TechEd+Barcelona+The+Steve+Clemens+Show.aspx</link>
      <pubDate>Wed, 29 Aug 2007 16:47:23 GMT</pubDate>
      <description>&lt;p&gt;
Even though the &lt;a href="http://www.mseventseurope.com/teched/07/developers/Pages/default.aspx"&gt;TechEd
Europe Developer&amp;nbsp;Website&lt;/a&gt; doesn't yet clearly say so, Steve Swartz and&amp;nbsp;myself&amp;nbsp;will
"of course!" be back with a new set of Steve &amp;amp; Clemens talks in Barcelona for
TechEd Europe Developer (November 5-9). And for the first time we'll stay for another
week and also give a talk at &lt;a href="http://www.mseventseurope.com/teched/07/itforum/Pages/Default.aspx"&gt;TechEd
Europe ITForum&lt;/a&gt; (November 12-16) this year. 
&lt;/p&gt;
&lt;p&gt;
What will we talk about? 
&lt;/p&gt;
&lt;p&gt;
Last year we've started with a history lesson, did a broad&amp;nbsp;and mostly technology
agnostic overview of&amp;nbsp;distributed systems architecture across&amp;nbsp;4 talks and
closed with a talk that speculated about the future. 
&lt;/p&gt;
&lt;p&gt;
This year at the TechEd Developer show, we'll be significantly more concrete and zoom
in on the technologies that make up the Microsoft SOA and Business Process platform
and show how things are meant to fit together. We'll talk about the rise of declarative
programming and composition and how that manifests in the .NET Framework and elsewhere.
And as messaging dudes we'll also talk about messaging again. At TechEd ITForum we'll&amp;nbsp;talk
about the end-to-end lifecycle of composite applications and how to manage it effectively.
&lt;/p&gt;
&lt;p&gt;
And of course there'll be "futures". Much less handwavy futures than last year, actually.
&lt;/p&gt;
&lt;p&gt;
So .... We'll be in Barcelona for TechEd. You too?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=a1692142-3221-4ecc-8e5f-5aff2635d714" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,a1692142-3221-4ecc-8e5f-5aff2635d714.aspx</comments>
      <category>Architecture</category>
      <category>Talks</category>
      <category>Talks/TechEd Europe</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=479cc904-6008-4d1d-ae2a-c53d5d101ce6</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,479cc904-6008-4d1d-ae2a-c53d5d101ce6.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,479cc904-6008-4d1d-ae2a-c53d5d101ce6.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=479cc904-6008-4d1d-ae2a-c53d5d101ce6</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
My first of two sessions this week here at TechEd is on Thursday, at 2:45pm in room
153ABC on "Designing Bindings and Contracts". 
</p>
        <p>
I realize that the title sounds a bit abstract and a different way to put this would
be "How to choose the correct bindings and what to consider about contracts in a variety
of architectual scenarios", but that would have been a bit long as a title. in the
talk I'll explain the system-defined bindings that we ship in the product so that
we've got stuff to work with and then I'll get out the tablet pen and draw up a bunch
of scenarios and how our bindings (read: communication options) make sense in those.
What's the best choice for N-Tier inside and outside of the corporate perimeter, what
do you do for queueing-style apps, how do you implement volatile or durable 1:1 pub/sub,
how do you implement broadcasts and where do they make sense, etc. 
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=479cc904-6008-4d1d-ae2a-c53d5d101ce6" />
      </body>
      <title>TechEd: What I am going to talk about on Thursday</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,479cc904-6008-4d1d-ae2a-c53d5d101ce6.aspx</guid>
      <link>http://vasters.com/clemensv/2006/06/13/TechEd+What+I+Am+Going+To+Talk+About+On+Thursday.aspx</link>
      <pubDate>Tue, 13 Jun 2006 16:09:57 GMT</pubDate>
      <description>&lt;p&gt;
My first of two sessions this week here at TechEd is on Thursday, at 2:45pm in room
153ABC on "Designing Bindings and Contracts". 
&lt;/p&gt;
&lt;p&gt;
I realize that the title sounds a bit abstract and a different way to put this would
be "How to choose the correct bindings and what to consider about contracts in a variety
of architectual scenarios", but that would have been a bit long as a title. in the
talk I'll explain the system-defined bindings that we ship in the product so that
we've got stuff to work with and then I'll get out the tablet pen and draw up a bunch
of scenarios and how our bindings (read: communication options) make sense in those.
What's the best choice for N-Tier inside and outside of the corporate perimeter, what
do you do for queueing-style apps, how do you implement volatile or durable 1:1 pub/sub,
how do you implement broadcasts and where do they make sense, etc. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=479cc904-6008-4d1d-ae2a-c53d5d101ce6" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,479cc904-6008-4d1d-ae2a-c53d5d101ce6.aspx</comments>
      <category>Architecture</category>
      <category>Technology/Indigo</category>
      <category>Technology/WCF</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=97913270-88a9-49b9-b057-2dcbdc3f9c90</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,97913270-88a9-49b9-b057-2dcbdc3f9c90.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,97913270-88a9-49b9-b057-2dcbdc3f9c90.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=97913270-88a9-49b9-b057-2dcbdc3f9c90</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <title>Autonomy isn't Autonomy - and a few words about Caching.</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,97913270-88a9-49b9-b057-2dcbdc3f9c90.aspx</guid>
      <link>http://vasters.com/clemensv/2006/06/01/Autonomy+Isnt+Autonomy+And+A+Few+Words+About+Caching.aspx</link>
      <pubDate>Thu, 01 Jun 2006 14:18:43 GMT</pubDate>
      <description>&lt;div class=Section1&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;&lt;?xml:namespace prefix = o /&gt;A question that is raised quite often
in the context of “SOA” is that of how to deal with data. &amp;nbsp;Specifically, people
are increasingly interested in (and concerned about) appropriate caching strategies.
What I see described in that context is often motivated by the fundamental misunderstanding
that the SO tenet that speaks about ”automony” is perceived to mean “autonomous computing”
while it really means “avoid coupling”. The former is an architecture prescription,
the latter is just a statement about the quality of a network edge.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;I will admit that it the use of “autonomy” confused me for a while
as well. Specifically, in my 5/2004 &lt;a href="http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=04cfedd9-12d3-4070-ab7c-b52bc67fda2d"&gt;“Data
Services”&lt;/a&gt; post, I’ve shown principles of autonomous computing and how there is
a benefit to loose coupling at the network edge when combined with autonomous computing
principles, but at the time I did not yet fully understand how orthogonal those two
things really are. I guess that one of the aspects of blogging is that you’ve got
to be ready to learn and evolve your knowledge in front of all people. Mind that I
stand by the architectural patterns and the notion of data services that I explained
in that post, except for the notion that the “Autonomy” SO tenet speaks about autonomous
computing. 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="TEXT-ALIGN: center" align=center&gt;
&lt;img id=" x0000 i1025" height=292 src="http://friends.newtelligence.net/clemensv/content/binary/image00112345678.png" width=484&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;The picture here illustrates the difference. By autonomous computing
principles the left shape of the service is “correct”. The service is fully autonomous
and protects its state. That’s a model that’s strictly following the Fiefdoms/Emissaries
idea that Pat Helland formulated a few years back. Very many applications look like
the shape on the right. There are a number of services sticking up that share a common
backend store. That’s not following autonomous computing principles. However, if you
look across the top, you’ll see that the endpoints (different colors, different contracts)
look precisely alike from the outside for both pillars. That’s the split: Autonomous
computing talks very much about how things are supposed to look behind your service
boundary (which is not and should not be anyone’s business but yours) and service
orientation really talks about you being able to hide any kind of such architectural
decision between a loosely coupled network edge. The two ideas compose well, but they
are not the same, at all.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;Which leads me to the greater story: In terms of software architecture,
“SOA” introduces very little new. All distributed systems patterns that have evolved
since the 1960 stay true. I haven’t really seen any revolutionary new architecture
pattern come out since we speak about Web Services. Brokers, Intermediaries, Federators,
Pub/Sub, Queuing, STP, Conversations – all of that has been known for a long time.
We’ve just commonly discovered that loose coupling is a quality that’s worth something.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;In all reality, the “SOA” hype is about the notion of aligning business
functions with software in order to streamline integration. SOA doesn’t talk about
software architecture; in other words: SOA does not talk about how to shape the mechanics
of a system. From a software architecture perspective, any notion of an “SOA revolution”
is complete hogwash. From a Business/IT convergence perspective – to drive analysis
and high-level design – there’s meat in the whole story, but I see the SOA term being
used mostly for describing technology pieces. “We are building a SOA” really means
“we are building a distributed system and we’re trying to make all parts loosely coupled
to the best of our abilities”. Whether that distributed system is indeed aligned with
the business functions is a wholly different story.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;However, I digress. Coming back to the data management issue, it’s
clear that a stringent autonomous computing design introduces quite a few challenges
in terms of data management. Data consolidation across separate stores for the purposes
of reporting requires quite a bit of special consideration and so does caching of
data. When the data for a system is dispersed across a variety of stores and comes
together only through service channels without the ability to freely query across
the data stores and those services are potentially “far” away in terms of bandwidth
and latency, data management becomes considerably more difficult than in a monolithic
app with a single store. However, this added complexity is a function of choosing
to make the service architecture follow autonomous computing principles, not one of
how to shape the service edge and whether you use service orientation principles to
implement it.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;To be clear: I continue to believe that aligning data storage with
services is a good thing. It is an additional strategy for looser coupling between
services and allows the sort of data patterns and flexibility that I have explained
in the post I linked to above. However, “your mileage may vary” is as true here as
anywhere. For some scenarios, tightly coupling services in the backyard might be the
right thing to do. That’s especially true for “service-enabling” existing applications.
All these architectural considerations are, however, strictly orthogonal to the tenets
of SO. 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;Generally, my advice with respect to data management in distributed
systems is to handle all data explicitly as part of the application code and not hide
data management in some obscure interception layer. There are a lot of approaches
that attempt to hide complex caching scenarios away from application programmers by
introducing caching magic on the call/message path. That is a reasonable thing to
do, if the goal is to optimize message traffic and the granularity that that gives
you is acceptable. I had a scenario where that was a just the right fit in one of
my last newtelligence projects. Be that as it may, proper data management, caching
included, is somewhat like the holy grail of distributed computing and unless people
know what they’re doing, it’s dangerous to try to hide it away. 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;That said, I believe that it is worth a thought to make caching a
first-class consideration in any distributed system where data flows across boundaries.
If it’s known at the data source that a particular record or set of records won’t
be updated until 1200h tomorrow (many banks, for instance, still do accounting batch
runs just once or twice daily) then it is helpful to flow that information alongside
the data to allow any receiver determine the caching strategy for the particular data
item(s). Likewise, if it’s know that a record or record set is unlikely to change
or even guaranteed to not change within an hour/day/week/month or if some staleness
of that record is typically acceptable, the caching metadata can indicate an absolute
or relative time instant at which the data has to be considered stale and possibly
a time instant at which it absolutely expires and must be cleaned from any cache.
Adding caching hints to each record or set of records allows clients to make a lot
better informed decisions about how to deal with that data. This is ultimately about
loose coupling and giving every participant of a distributed system enough information
to make their own decisions about how to deal with things.&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal&gt;
&lt;span lang=EN-US&gt;Which leaves the question about where to cache stuff. The instant
“obvious best idea” is to hold stuff in memory. However, if the queries into the cached
data become more complex than “select all” or reasonably simple hashtable lookups,
it’s not too unlikely that, if you run on Windows, a local SQL Server (-Express) instance
holding the cache data will do as good or better (increasingly with data volume) compared
a custom query “engine” in terms of performance – even if it serves data out from
memory. That’s especially true for caching frameworks that can be written within the
time/budget of a typical enterprise project. Besides, long-lived cached data whose
expiration window exceeds the lifetime of the application instance needs a home, too.
One of the bad caching scenarios is that the network gets saturated at 8 in the morning
when everybody starts up their smart client apps and tries to suck the central database
dry at once – that’s what in-memory database approaches cause.&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=97913270-88a9-49b9-b057-2dcbdc3f9c90" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,97913270-88a9-49b9-b057-2dcbdc3f9c90.aspx</comments>
      <category>Architecture</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=b5cab8d6-b2a7-437e-a876-069ef63f14eb</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,b5cab8d6-b2a7-437e-a876-069ef63f14eb.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,b5cab8d6-b2a7-437e-a876-069ef63f14eb.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=b5cab8d6-b2a7-437e-a876-069ef63f14eb</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.intertwingly.net/blog/2006/04/17/Two-Webs">+5 Insightful</a>
        </p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b5cab8d6-b2a7-437e-a876-069ef63f14eb" />
      </body>
      <title>SOAP/REST split is a safe/unsafe split </title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,b5cab8d6-b2a7-437e-a876-069ef63f14eb.aspx</guid>
      <link>http://vasters.com/clemensv/2006/04/18/SOAPREST+Split+Is+A+Safeunsafe+Split.aspx</link>
      <pubDate>Tue, 18 Apr 2006 05:29:42 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://www.intertwingly.net/blog/2006/04/17/Two-Webs"&gt;+5 Insightful&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=b5cab8d6-b2a7-437e-a876-069ef63f14eb" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,b5cab8d6-b2a7-437e-a876-069ef63f14eb.aspx</comments>
      <category>Architecture</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=92eaea8c-778d-4512-af03-d332785f65f5</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,92eaea8c-778d-4512-af03-d332785f65f5.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,92eaea8c-778d-4512-af03-d332785f65f5.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=92eaea8c-778d-4512-af03-d332785f65f5</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I kicked off quite a discussion with my <a href="http://friends.newtelligence.net/clemensv/CommentView,guid,0fbf07a9-9e7a-4db4-a305-58250ac57a73.aspx">recent
post</a> on O/R mapping. Some people think I am completely wrong, some say that it
resonates with their experience, some say I wrote this in mean spirit, some are jubilating.
I particularly liked the "<a href="http://www.from9till2.com/PermaLink.aspx?guid=6e734626-29df-4971-b17d-dcaf7a0e6ab1">Architectural
Truthiness</a>" post by David Ing and the comment by "Scott E" in my comments section
who wrote:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <em>I've hiked up the learning curve for Hibernate (the Java flavor) only to find
that what time was saved in mapping basic CRUD functionality got eaten up by out-of-band
custom data access (which always seems to be required) and tuning to get performance
close to what it would have been with a more specialized, hand-coded DAL. </em>
          </p>
        </blockquote>
        <p>
As always, it's a matter of perspective. Here is mine: I went down the O/R mapping
route in a project in '98/'99 when my group at the company I was working for at the
time was building a new business framework. We wrote a complete, fully transparent O/R
mapper in C++. You walked up to a factory which dehydrated objects and you could walk
along the association links and the object graph would either incrementally dehydrate
or dehydrate in predefined segments. We had filtering capabilities that allowed
to constrain 1:N collections with large N's, we could auto-resolve N:M relationships,
had support for inheritance, and all that jazz. The whole framework was written
with code generation in mind. Our generators were fed with augmented UML class diagrams
and spit out the business layer, whereby we had a "partial classes" concept where
we'd keep the auto-gen'd code in one tree and the parts that were supposed to be filled
manually in another part of the code tree. Of course we'd preserve changes across
re-gen's. Pure OO nirvana. 
</p>
        <p>
While the platforms have evolved substantially in the past 7 years, the fundamental
challenges for transparent (fully abstracted) mapping of data to objects remain essentially
the same. 
</p>
        <ul>
          <li>
Given metadata to do the mapping, implementing CRUD functionality with an O/R mapper is quite
easy. We had to put lots of extra metadata into our C++ classes back in the day, but
with .NET and Java the metadata is all there and therefore CRUD O/R mapping is very
low-hanging fruit on both platforms. That's why there's such a large number of projects
and products.</li>
          <li>
Defining and resolving associations is difficult. 1:N is hard, because you need to
know what your N looks like. You don't want to dehydrate 10000 objects to find a value
in one of them or to calculate a sum over a column. That's work that's, quite frankly, best
left in the database. I realize that some people worry how that leads to logic bleeding
into the database, but for me that's a discussion about pureness vs. pragmatism. If
the N is small, grabbing all related objects is relatively easy - unless you support
polymorphism, which forces the mapper into all sorts of weird query trees. 1:N is
so difficult because an object model is inherently about records, while SQL is about
sets. N:M is harder.</li>
          <li>
"Object identity" is a dangerous lure. Every object has its own identifier. In memory
that is its address, on disk that's some form of unique identifier. The idea of making
the persistent identifier also the in-memory identifier often has the design consequence
of an in-memory "running object table" with the goal of avoiding to load the same
object twice but rather linking it appropriately into the object graph. That's a
fantastic concept, but leads to all sort of interesting concurrency puzzles: What
do you do if you happen to find an object you have already loaded as you resolve an
1:N association and realize that the object has meanwhile changed on disk? Another
question is what the scope of the object identity is. Per appdomain/process, per machine
or even a central object server (hope not)?</li>
          <li>
Transactions are hard. Databases are doing a really good job with data concurrency
management, especially with stored procedures. If you are loading and managing
data as object-graphs, how do you manage transaction isolation? How do you identify
the subtree that's being touched by a transaction? How do you manage rollbacks? What
is a transaction, anyways?</li>
          <li>
Changing the underlying data model is hard. I've run into several situations where
existing applications had to be, with the customer willing to put money on the
table, be integrated with existing data models. O/R mapping is relatively easy
of the data model falls out of the object model. If an existing data model
bubbles up against an object model, you often end up writing a DAL or the O/R in stored
procedures.</li>
          <li>
Reporting and data aggregation is hard. I'll use an analogy for that: It's really
easy to write an XPath query against an XML document, but it is insanely difficult
to do the same navigating the DOM.</li>
        </ul>
        <p>
That said, I am not for or against O/R mapping. There are lots of use cases with a
lot of CRUD work where O/R saves a lot of time. However, it is a leaky abstraction.
In fact is is so leaky that we ended up not using all that much of the funkyness we
put into our framework, because "special cases" kept popping up. I am pointing out
that there are a lot of fundamental differences between what an RDBMS does with data
and how OOP treats data. The discussion is in part a discussion about ISAM
vs. RDBMS. 
</p>
        <p>
The number of brain cycles that need to be invested for a clean O/R mapping
of a complex object model in the presence of the fundamental challenges I listed here
(and that list isn't exhaustive) are not automatically less than for a plain-old
data layer. It may be more. YMMV.
</p>
        <p>
Now you can (and some already have) ask how all of that plays with <a href="http://msdn.microsoft.com/netframework/future/linq/">LINQ</a> and,
in particular, <a href="http://download.microsoft.com/download/c/f/b/cfbbc093-f3b3-4fdb-a170-604db2e29e99/DLinq%20Overview.doc">DLINQ</a>.
Mind that I don't work in the LINQ team, but I think to be observing
a subtle but important difference between LINQ and O/R*: 
</p>
        <ul>
          <li>
O/R is object-&gt;relational mapping. 
</li>
          <li>
LINQ is relational-&gt;object mapping. 
</li>
        </ul>
        <p>
LINQ acknowledges the relational nature of the vast majority of data, while O/R attempts
to deny it. LINQ speaks about entities, relations and queries and maps result-sets
into the realm of objects, even cooking up classes on the fly if it needs to. It's
bottom up and the data (from whatever source) is king. Objects and classes are just
tooling. For O/R mapping, the database is just tooling.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=92eaea8c-778d-4512-af03-d332785f65f5" />
      </body>
      <title>O/R mapping; take two</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,92eaea8c-778d-4512-af03-d332785f65f5.aspx</guid>
      <link>http://vasters.com/clemensv/2006/03/14/OR+Mapping+Take+Two.aspx</link>
      <pubDate>Tue, 14 Mar 2006 14:17:53 GMT</pubDate>
      <description>&lt;p&gt;
I kicked off quite a discussion with my &lt;a href="http://friends.newtelligence.net/clemensv/CommentView,guid,0fbf07a9-9e7a-4db4-a305-58250ac57a73.aspx"&gt;recent
post&lt;/a&gt; on O/R mapping. Some people think I am completely wrong, some say that it
resonates with their experience, some say I wrote this in mean spirit, some are jubilating.
I particularly liked the "&lt;a href="http://www.from9till2.com/PermaLink.aspx?guid=6e734626-29df-4971-b17d-dcaf7a0e6ab1"&gt;Architectural
Truthiness&lt;/a&gt;" post by David Ing and the comment by "Scott E" in my comments section
who wrote:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;em&gt;I've hiked up the learning curve for Hibernate (the Java flavor) only to find
that what time was saved in mapping basic CRUD functionality got eaten up by out-of-band
custom data access (which always seems to be required) and tuning to get performance
close to what it would have been with a more specialized, hand-coded DAL. &lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
As always, it's a matter of perspective. Here is mine: I went down the O/R mapping
route in a project in '98/'99 when my group at the company I was working for at the
time was building a new business framework. We wrote&amp;nbsp;a complete, fully transparent&amp;nbsp;O/R
mapper in C++. You walked up to a factory which dehydrated objects and you could walk
along the association links and&amp;nbsp;the object graph would either incrementally dehydrate
or dehydrate in&amp;nbsp;predefined segments. We had filtering capabilities that&amp;nbsp;allowed
to constrain 1:N collections with large N's, we could auto-resolve N:M&amp;nbsp;relationships,
had support for inheritance,&amp;nbsp;and all that jazz. The whole framework was written
with code generation in mind. Our generators were fed with augmented UML class diagrams
and spit out the business layer, whereby we had a "partial classes" concept where
we'd keep the auto-gen'd code in one tree and the parts that were supposed to be filled
manually in another part of the code tree. Of course we'd preserve changes across
re-gen's. Pure OO nirvana. 
&lt;/p&gt;
&lt;p&gt;
While the platforms have evolved substantially in the past 7 years, the fundamental
challenges for transparent (fully abstracted) mapping of data to objects remain essentially
the same. 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Given metadata to do the mapping, implementing CRUD functionality with an O/R mapper&amp;nbsp;is&amp;nbsp;quite
easy. We had to put lots of extra metadata into our C++ classes back in the day, but
with .NET and Java the metadata is all there and therefore CRUD O/R mapping is very
low-hanging fruit on both platforms. That's why there's such a large number of projects
and products.&lt;/li&gt;
&lt;li&gt;
Defining and resolving associations is difficult. 1:N is hard, because you need to
know what your N looks like. You don't want to dehydrate 10000 objects to find a value
in one of them or to calculate a sum over a column. That's work that's, quite frankly,&amp;nbsp;best
left in the database. I realize that some people worry how that leads to logic bleeding
into the database, but for me that's a discussion about pureness vs. pragmatism. If
the N is small, grabbing all related objects is relatively easy - unless you support
polymorphism, which forces the mapper into all sorts of weird query trees. 1:N is
so difficult because an object model is inherently about records, while SQL is about
sets. N:M is harder.&lt;/li&gt;
&lt;li&gt;
"Object identity" is a dangerous lure. Every object has its own identifier. In memory
that is its address, on disk that's some form of unique identifier. The idea of making
the persistent identifier also the in-memory identifier often has the design consequence
of an in-memory "running object table" with the goal of avoiding to load the same
object twice but rather linking it appropriately into the object graph. That's&amp;nbsp;a
fantastic concept, but leads to all sort of interesting concurrency puzzles: What
do you do if you happen to find an object you have already loaded as you resolve an
1:N association and realize that the object has meanwhile changed on disk? Another
question is what the scope of the object identity is. Per appdomain/process, per machine
or even a central object server (hope not)?&lt;/li&gt;
&lt;li&gt;
Transactions are hard. Databases are doing a really good job with data concurrency
management, especially with stored procedures.&amp;nbsp;If you are&amp;nbsp;loading and managing
data as object-graphs, how do you manage transaction isolation?&amp;nbsp;How do you identify
the subtree that's being touched by a transaction? How do you manage rollbacks?&amp;nbsp;What
is a transaction, anyways?&lt;/li&gt;
&lt;li&gt;
Changing the underlying data model is hard. I've run into several situations where
existing applications had to be, with the customer&amp;nbsp;willing to put money on the
table,&amp;nbsp;be integrated with existing data models. O/R mapping is relatively easy
of the data model falls out of the object model. If&amp;nbsp;an existing&amp;nbsp;data model
bubbles up against an object model, you often end up writing a DAL or the O/R in stored
procedures.&lt;/li&gt;
&lt;li&gt;
Reporting and data aggregation is hard. I'll use an analogy for that: It's really
easy to write an XPath query against an XML document, but it is insanely difficult
to do the same navigating the DOM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
That said, I am not for or against O/R mapping. There are lots of use cases with a
lot of CRUD work where O/R saves a lot of time. However, it is a leaky abstraction.
In fact is is so leaky that we ended up not using all that much of the funkyness we
put into our framework, because "special cases" kept popping up. I am pointing out
that there are a lot of fundamental differences between what an RDBMS does with data
and how OOP treats data. The discussion is&amp;nbsp;in part&amp;nbsp;a discussion about ISAM
vs. RDBMS. 
&lt;/p&gt;
&lt;p&gt;
The number of brain cycles that need to be invested&amp;nbsp;for a clean&amp;nbsp;O/R mapping
of a complex object model in the presence of the fundamental challenges I listed here
(and that list isn't exhaustive) are not automatically less than for a&amp;nbsp;plain-old
data layer. It may be more. YMMV.
&lt;/p&gt;
&lt;p&gt;
Now you can (and some already have) ask how all of that plays with &lt;a href="http://msdn.microsoft.com/netframework/future/linq/"&gt;LINQ&lt;/a&gt;&amp;nbsp;and,
in particular, &lt;a href="http://download.microsoft.com/download/c/f/b/cfbbc093-f3b3-4fdb-a170-604db2e29e99/DLinq%20Overview.doc"&gt;DLINQ&lt;/a&gt;.
Mind that I don't work in&amp;nbsp;the LINQ&amp;nbsp;team, but I&amp;nbsp;think to be observing
a subtle but important difference between LINQ and O/R*:&amp;nbsp;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
O/R is object-&amp;gt;relational mapping. 
&lt;/li&gt;
&lt;li&gt;
LINQ is relational-&amp;gt;object mapping. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
LINQ acknowledges the relational nature of the vast majority of data, while O/R attempts
to deny it. LINQ speaks about entities, relations&amp;nbsp;and queries and maps result-sets
into the realm of objects, even cooking up classes on the fly if it needs to. It's
bottom up and the data (from whatever source) is king. Objects and classes are just
tooling. For O/R mapping, the database is just tooling.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=92eaea8c-778d-4512-af03-d332785f65f5" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,92eaea8c-778d-4512-af03-d332785f65f5.aspx</comments>
      <category>Architecture</category>
      <category>Technology</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=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=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=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=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=f6a0ff09-2c85-4bc7-b278-659d96f78eee</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,f6a0ff09-2c85-4bc7-b278-659d96f78eee.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,f6a0ff09-2c85-4bc7-b278-659d96f78eee.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=f6a0ff09-2c85-4bc7-b278-659d96f78eee</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Jimmy Nilsson is really good at <a href="http://www.jnsk.se/weblog/posts/toclemens.htm">spotting</a> flamebait.
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=f6a0ff09-2c85-4bc7-b278-659d96f78eee" />
      </body>
      <title>Got caught</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,f6a0ff09-2c85-4bc7-b278-659d96f78eee.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/09/Got+Caught.aspx</link>
      <pubDate>Fri, 09 Jul 2004 09:10:16 GMT</pubDate>
      <description>&lt;p&gt;
Jimmy Nilsson is really good at &lt;a href="http://www.jnsk.se/weblog/posts/toclemens.htm"&gt;spotting&lt;/a&gt; flamebait.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=f6a0ff09-2c85-4bc7-b278-659d96f78eee" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,f6a0ff09-2c85-4bc7-b278-659d96f78eee.aspx</comments>
      <category>Architecture</category>
    </item>
    <item>
      <trackback:ping>http://vasters.com/clemensv/Trackback.aspx?guid=e37002f1-7d22-4270-aa9f-487417237b66</trackback:ping>
      <pingback:server>http://vasters.com/clemensv/pingback.aspx</pingback:server>
      <pingback:target>http://vasters.com/clemensv/PermaLink,guid,e37002f1-7d22-4270-aa9f-487417237b66.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://vasters.com/clemensv/CommentView,guid,e37002f1-7d22-4270-aa9f-487417237b66.aspx</wfw:comment>
      <wfw:commentRss>http://vasters.com/clemensv/SyndicationService.asmx/GetEntryCommentsRss?guid=e37002f1-7d22-4270-aa9f-487417237b66</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Do I do this because I want to or do I do this because I need to?
</p>
        <img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e37002f1-7d22-4270-aa9f-487417237b66" />
      </body>
      <title>Architect's Introspection</title>
      <guid isPermaLink="false">http://vasters.com/clemensv/PermaLink,guid,e37002f1-7d22-4270-aa9f-487417237b66.aspx</guid>
      <link>http://vasters.com/clemensv/2004/07/08/Architects+Introspection.aspx</link>
      <pubDate>Thu, 08 Jul 2004 12:48:11 GMT</pubDate>
      <description>&lt;p&gt;
Do I do this because I want to or do I do this because I need to?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://vasters.com/clemensv/aggbug.ashx?id=e37002f1-7d22-4270-aa9f-487417237b66" /&gt;</description>
      <comments>http://vasters.com/clemensv/CommentView,guid,e37002f1-7d22-4270-aa9f-487417237b66.aspx</comments>
      <category>Architecture</category>
    </item>
  </channel>
</rss>