<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-12390913</id><updated>2011-04-21T21:02:03.317-07:00</updated><category term='MVP'/><category term='Data'/><category term='Bill Gates'/><category term='Microsoft'/><category term='Contracts'/><category term='Schemas'/><title type='text'>Making SOA Real</title><subtitle type='html'>An SOA odyssey</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>49</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-12390913.post-90031722033566932</id><published>2007-06-21T07:12:00.001-07:00</published><updated>2007-06-21T08:52:53.498-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Contracts'/><category scheme='http://www.blogger.com/atom/ns#' term='Schemas'/><title type='text'>Integrated Concepts</title><content type='html'>&lt;a href="http://blogs.msdn.com/nickmalik/archive/2007/06/12/canonical-model-canonical-schema-and-event-driven-soa.aspx"&gt;This posting passed on by a colleague&lt;/a&gt; I find particularly interesting as it relates to our SOA implementation. The idea is that the four concepts:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Enterprise Canonical Data Model&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Canonical Message Schema &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Event Driven Architecture&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Business Event Ontology&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;are intimately related and the post goes through the touch points for each. What I appreciate here is the separation of the canonical data model from the canonical message schema. In our implementation we create XSD to represent the business entities (analogous to the enterprise canonical data model) and then wrap various parts of these in XSD when creating the response, request, and acknowledgement message contracts (canonical message schemas). &lt;br /&gt;&lt;br /&gt;But although we have a handle on these concepts I think it's important to really keep an eye on raising the visibility of the canonical data model from within the project team to the entire IT organizational level (thus making it canonical). Unfortunately we haven't been able to do this very successfully and so that limits the usefulness of the model both because we may not have considered what we need to and therefore the models may not be as robust as eventually needed, and since other groups may be off developing similar models that we don't know about. In order to address these limitations we're working with our architecture group to publish a "service catalog" that surfaces the schemas and their semantics along with what's been implemented thus far so that within the organization we'll be better able to communicate on a shared foundation. To do this we're contributing to a wiki that's been setup in Microsoft Office Sharepoint Server 2007. &lt;br /&gt;&lt;br /&gt;In addition, while the messaging contracts are certainly useful they are not very flexible. In a second generation implementation we hope to move towards a more &lt;a href="http://martinfowler.com/articles/consumerDrivenContracts.html"&gt;consumer-driven contract approach&lt;/a&gt; that retains the canonical data model schemas but allows consumers to pick and choose more easily the data they require. &lt;br /&gt;&lt;br /&gt;On the fourth bullet we haven't been as forward-thinking as we would like. Although our implementation platform allows for the publication and consumption of business events we haven't integrated that publication into our infrastructure. Of course, as the poster mentions, first you need to figure out just what those events are and I'm hopeful that the idea of cataloguing those will gain some traction going forward.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-90031722033566932?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/90031722033566932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=90031722033566932&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/90031722033566932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/90031722033566932'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2007/06/integrated-concepts.html' title='Integrated Concepts'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-5530746900538902322</id><published>2007-03-14T16:27:00.000-07:00</published><updated>2007-03-14T20:19:32.661-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVP'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>MVP Summit Day 2</title><content type='html'>Day 2 of the MVP Summit was spent in building 43 on the Microsoft campus, the home of the Connected Systems Division. Right away what I liked about their approach to the event was that the sessions CSD delivered were not targeted to a single MVP focus (BizTalk for example) but rather to a larger group that included Solutions Architects and others. In essence the sessions were designed to give us the broad picture of how everything in the division interconnects, which, if you think about it, should be a primary focus of their division.&lt;br /&gt;&lt;br /&gt;Just a quick note on last night's activities. The attendee dinner was held at &lt;a href="http://www.museumofflight.org/Portal.asp?Flash=True"&gt;The Museum of Flight&lt;/a&gt; south of downtown and it was a fabulous event. For some reason I had never made it to the museum and was absolutely floored by the quantity and quality of the exhibits. What was particularly interesting to me were the myriad examples of fighter planes from World War I up to the current day with brief but informative descriptions of each. The exhibits were also grouped by time period so a British Spitfire was next to the German Messerschmitt and the planes the US Navy flew were next to the Japanese versions which allowed you to compare and contrast them. The displays were also interesting in that along with a description of a specific kind of plane a brief blurb about the founder of the various aircraft companies as appropriate and the history of the museum's particular example of that aircraft. &lt;br /&gt;&lt;br /&gt;In any case the first talk today was given by Sonu Arora, Program manager in CSD and Jesus Rodriguez, the Chief Software Architect of a company called Two Connect. Their topic was titled "Line of Business Adapter with WCF Deep Dive". Essentially the LOB Adapter is a new SDK for building adapters (termed the LOB adapter SDK where LOB refers to any backend application such as SAP, PeopleSoft and even custom databases) to integrate LOB applications with WCF clients. To that end the result is integration with your line of business applications that are…&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Surfaced as WCF Binding&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Can be consumed using WCF channel/service programming model&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;The strength of this approach is that it moves the adapter out of BizTalk and the other Microsoft products (for example Microsoft today has five SAP "adapters" strewn about their products) where it can be reused. In all, very interesting stuff. &lt;br /&gt;&lt;br /&gt;The second session of the day was given by David Hill PM Tech Lead in the UI Framework regarding a topic that is still under NDA but is related to the existing client application block (CAB), Smart Client Software Factory, and WPF work being done and targeted for the post Visual Studio Orcas timeframe.&lt;br /&gt;&lt;br /&gt;The third session was given by Jack Greenfield of &lt;a href="http://msdn2.microsoft.com/en-us/teamsystem/aa718951.aspx"&gt;Software Factories fame&lt;/a&gt; where he first discussed the current state of the software factory and software product lines and then moved on to the plans (under NDA) for this space under Rosario. &lt;br /&gt;&lt;br /&gt;One of the things I did find interesting in his review of the current state of things is when he showed a slide that include a continuum of guidance evolution. The evolution starts with written guidelines, moves on to standard patterns, evolves to templates that can be reused in tools, then to frameworks that templates often rely on, and finally to visual designers that are integrated into the tool. This is interesting since in our project we're entering the template and frameworks stages by developing a set of CodeSmith templates to drive the development of new services by hooking into our existing service provider and service consumer frameworks. I'm not certain we'll ever get to visual designers or that we'll ever need to, but the topic reminded me that there is a continuum here and in my experience there is a large gulf between guidance/patterns and templates/frameworks and that is where you can really drive adoption. Until there is some actual help outside of the printed word, it is difficult for developers to adopt a new framework. &lt;br /&gt;&lt;br /&gt;Next, we were off to building 5 and the home of the Patterns and Practices group where we took a tour of their agile-enabled redesigned space. In a nutshell the P&amp;P group worked with a team of architects over a three to four month period and ended up rearchitecting their space for their teams that doing a mix of Scrum and Agile development. &lt;br /&gt;&lt;br /&gt;The space, which accommodates up to 50 people, is now split into five team rooms wrapped by a ring of offices on a raised floor where literally the walls of all the team rooms and the offices are moveable. Each of the team rooms has desks with low dividers that can be configured in any way the team likes to the extent where the power coming from the floor can be moved along with the tables. The walls of each of the team rooms is double pane glass with a white material between them so they can be written on from floor to ceiling. Each of the team rooms was configured differently with some teams working in a circle sort of like a traditional conference room while others were staggered throughout the room. Not all of the walls had the white surface, however, and neither did the glass doors since one of the design criteria was that no matter where a team member sits, they can see outdoors. Each room also had a projector and conference phone and each phone at the workstations use IP and so can be moved as developers move around. The workstations themselves are all dual monitor (every team member uses a laptop) as well with their own lighting. &lt;br /&gt;&lt;br /&gt;The outside offices are used for a variety of purposes ranging from a dedicated customer room where customers have a place to call home while working with the team to a series of offices some of which are actually dual offices for product managers and others. Interestingly, they also have a dedicated "quiet room" (my term) where a developer can get away from their team in order to make a phone call or otherwise take a break from their teammates. From the feedback I've gotten from the team I worked on who worked in a war room environment for several months, this is probably an essential aspect of this kind of team environment.&lt;br /&gt;&lt;br /&gt;In taking the tour it was also noted that the P&amp;P group of course uses Team Foundation Server but does not use MSBuild but rather CruiseControl to do their builds. They're also working their way through how to use the process guidance in TFS as the different teams have used different templates and use those different templates in various ways.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-5530746900538902322?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/5530746900538902322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=5530746900538902322&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/5530746900538902322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/5530746900538902322'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2007/03/mvp-summit-day-2.html' title='MVP Summit Day 2'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-1082490555355305262</id><published>2007-03-13T13:16:00.000-07:00</published><updated>2007-03-15T07:02:50.556-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVP'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Developer Division Update</title><content type='html'>The Developer Division hour long session at the MVP summit was given by the corporate Vice President of the division by &lt;a href="http://blogs.msdn.com/somasegar/"&gt;S. Somasegar&lt;/a&gt;. He started by presenting an overview of what has been happening within the division since the release of Visual Studio 2005 some 16 months ago.  This included reviews of .NET 3.0 with WFC and WWF, ASP.NET Ajax, Team Foundation Server, the MSDN Wiki beta, and the March CTP of the Orcas release of Visual Studio. He then proceeded to bring out a presenter to do a demo of the Office 2007 integration with Orcas related to "forms regions". Essentially, as shown in the demo, within Orcas developers will have an add-in makes it fairly simple to integrate outside content into Outlook. The most interesting of the demos that he showed integrated additional features into contact management where clicking on a contact used Windows Live Services to pull down maps of the location within a pane inside outlook. He also showed a demo where business data on specific clients was brought up in a separate pane (using a WPF control highlighting the cool UI features) when an email from that client was selected. Interesting stuff.&lt;br /&gt;&lt;br /&gt;Somasegar then went on to point out that "friction free" deployment was one of their big challenges and something they've been working hard on. He followed this with a demo of &lt;a href="http://channel9.msdn.com/playground/wpfe/"&gt;WPF/E (Windows Presentation Foundation Everywhere)&lt;/a&gt; (there was a CTP in February) and is the subset technology of &lt;a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation"&gt;WPF&lt;/a&gt; allowing rich multimedia experiences to be embedded on web pages using XAML and scripted using Javascript. &lt;br /&gt;&lt;br /&gt;The demo was interesting in that it showed one of WPF/E enhanced capabilities to deal with inking. In the demo the user on the web was able to annotate an image or a video and then when posted back to the server (you could also use Ajax) and saved, the page would allow for searching the video stream for the annotation, seeking to it, and then replaying the inking on the screen. &lt;br /&gt;&lt;br /&gt;He then answered a few questions and noted that PDC will be held this year in early October in Los Angeles. &lt;br /&gt;&lt;br /&gt;At several points in the talk he was also very high on &lt;a href="http://msdn2.microsoft.com/en-us/netframework/aa904594.aspx"&gt;LINQ&lt;/a&gt; and urged those in attendance to take in the talk later today on the subject. It will also be included in Orcas and brings &lt;a href="http://msdn2.microsoft.com/en-us/library/aa479865.aspx"&gt;query capability down into the CLR&lt;/a&gt; and provides extensions to support both relational and XML data stores.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-1082490555355305262?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/1082490555355305262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=1082490555355305262&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/1082490555355305262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/1082490555355305262'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2007/03/developer-division-roadmap.html' title='Developer Division Update'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-6793109477054419932</id><published>2007-03-13T11:25:00.000-07:00</published><updated>2007-03-13T11:27:24.341-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVP'/><category scheme='http://www.blogger.com/atom/ns#' term='Bill Gates'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Global MVP Summit</title><content type='html'>After a &lt;a href="http://www.baseballprospectus.com/article.php?articleid=5966"&gt;brief visit to several spring training sites over the weekend&lt;/a&gt; I'm here in Seattle attending the Microsoft MVP Summit. This is the annual event where 1,700 Most Valuable Professionals from 90 plus countries gather to attend over 500 sessions and to give Microsoft feedback on their products. These MVPs (and I admit I'm woefully lacking in that area) do much of their work in newsgroups and provided over 28,000 answers (21% of all answers) to questions in the MSDN forums last year. I'm in the Visual Developer group as a Solutions Architect and will be attending many of the developer tracks and hopefully providing some commentary over the next several days.&lt;br /&gt;&lt;br /&gt;In this morning's keynote Bill Gates spoke for about 20 minutes on the evolution of technology in Microsoft's just over 30 years in the industry. He hit all of the common themes from the growth in computing power via Moore's Law to the growth in multi-core computing (predicting 16 to 32 processors for desktop machines in 4 to 5 years) to the increasing availability of wireless technologies and it's expansion into the so-called "white space" that will allow for entire cities to provide wireless access. He also spent some time discussing graphics and video technologies and Microsoft's desire to raise the level of abstraction by providing APIs in the core operating systems that include the physics components and that also harness the power of the emerging multi-processor architectures. He sees video in many ways as the "final frontier" because of the challenges it posed in the past in terms of storage and processing power and he forsees the integration, cataloguing, and retrieval of video from a wide range of sources (colleges like MIT making their lectures freely available, businesses in corporate training, home and local use as in children's sporting events) as the next major application of the technology.&lt;br /&gt;&lt;br /&gt;He also took question for over a half hour fielding a wide range of queries related to the history of Microsoft and its products, the decline of computer science graduates in the US, the role of information technology in disaster scenarios such as that posed by Katrina and 911 (he reference the show 24 in his answer to this one noting how the integration of systems that the CTU can tie into does not exist in the real world today), and the struggles of Windows Search. &lt;br /&gt;&lt;br /&gt;Now it's on to the Developer Division Roadmap session.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-6793109477054419932?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/6793109477054419932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=6793109477054419932&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/6793109477054419932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/6793109477054419932'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2007/03/global-mvp-summit.html' title='Global MVP Summit'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-7829117504160455060</id><published>2006-11-28T11:11:00.000-08:00</published><updated>2006-11-28T11:29:02.496-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Data'/><title type='text'>Service Patterns and Data</title><content type='html'>I was alerted to &lt;a href="http://www.infoq.com/articles/SOA-enterprise-data"&gt;this interesting article&lt;/a&gt; titled "Incorporating Enterprise Data into SOA" by a colleague and wanted to pass it along. &lt;br /&gt;&lt;br /&gt;What I find interesting is that in our services implementation here we've built a mix of the first two patterns he discusses.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Aligning Enterprise Data Support with the Business Services&lt;/strong&gt;. Here, our business services (meaning service operations) define and implement the rules for data validation and encapsulate the storing and retrieving particular sets of data albeit with the help of a set of "manager" classes that we use to decouple the data access logic &lt;a href="http://realsoa.blogspot.com/2005/09/selecting-edaf.html"&gt;from our EDAF implementation&lt;/a&gt;. This is most clearly evidenced in our service contracts by the fact that our "select" request schemas include the concept of "zones". Essentially, the long term data architecture at Compassion calls for data to be distributed in a series of zones ranging from OLTP to data warehouse cubes with the appropriate aging and flattening of the data as it flows through the zones. &lt;br /&gt;&lt;br /&gt;To support this we created a schema that is a simple enumeration of zones and that can be included as an optional attribute in the envelope for service request schemas like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;xs:attribute ref="ds:DataStore" use="optional" /&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Service consumers then set the zone accordingly and it is up to the service operation both to interpret the zone and retrieve the data from the appropriate location (perhaps even using different data access mechanisms). Clearly, here is a case where our business services know alot about our enterprise data.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Enterprise Data Access as a business service&lt;/strong&gt;. Here some of the service operations we've built can be thought of as CRUD operations albeit with higher granularity thereby not falling into the "anti-pattern" category he mentions. For example, service operations such as LocateNeed which selects available children for sponsoring based on a set of rules and criteria, and QueryPaymentRelationshipSummary which summarizes and returns sets of monetary relationships between Compassion and our constituents are clearly well-aligned with business functionality.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;That said, the tension between these two is what has led the schemas we developed to be in some cases &lt;a href="http://realsoa.blogspot.com/2006/07/always-learning.html"&gt;too tightly bound to the existing enterprise data model&lt;/a&gt;. In a perfect world it would have been nice to work with a re-designed enterprise data model and to build a pure data services layer (enterprise data bus) on top of that which incorporates the concept of zones, validation, and entity aggregation that the more business oriented services would interact with.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-7829117504160455060?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/7829117504160455060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=7829117504160455060&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/7829117504160455060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/7829117504160455060'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/11/service-patterns-and-data.html' title='Service Patterns and Data'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-7895080439026035181</id><published>2006-10-26T08:18:00.000-07:00</published><updated>2006-10-26T08:59:11.079-07:00</updated><title type='text'>Business Process Improvement</title><content type='html'>While thinking on the subject I thought I'd update the status of our project. We rolled out the final of our four releases (code named "Bread &amp; Butter" and the most complex since it handled all types of money relationships including making payments on sponsorships, setting up new sponsorships with credit cards etc.) at the end of July and experienced a bit of a bumpy ride. After the rollout we were in a hotfix mode for roughly 30 days where we made incremental releases to various components every few days in order to handle issues that were not evidenced by our user acceptance testing. Unfortunately the release schedule was heavily influenced by some external business realities that the team didn't control and which forced us into the tradeoff situation we found ourselves in.&lt;br /&gt;&lt;br /&gt;At this point however, the infrastructure has handled over 125,000 business transactions and 3.5M service invocations with system exceptions under 1%. The interesting thing, and the most important of course, is that 70% of the business transactions now go down the happy path and do not involve human interaction. That 30% that do require human interaction, however, are ripe for process improvements and additional incremental automation that will allow that number to shrink dramatically. There are two interesting aspects that came out of this however.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;First, when you're implementing a business process management solution like this you should probably educate the business that there will be some low hanging fruit that comes out of the statistics generated after the release. As a result, they'll probably want to budget some resources for addressing these things in a final phase of the project. In our case, the project team is set to disband and the resources were not allocated and so the low hanging fruit will have to wait for another project. When that will exactly be is yet to be determined.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;It's extrememly important to define &lt;i&gt;before&lt;/i&gt; the project both the strategy for collection and the kinds of metrics you want to collect. The obvious reason is that these metrics will embody the questions that the business will ask and therefore point to where the process improvements can take place. In our implementation we did not do a thorough enough job of either collection or understanding and as a result there are some holes in our ability to ask the right questions. We're attempting to address some of this in a followup project but as you can imagine it's more difficult at this stage than it would have been if integrated into the early iterations of the project.&lt;/li&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-7895080439026035181?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/7895080439026035181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=7895080439026035181&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/7895080439026035181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/7895080439026035181'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/10/business-process-improvement.html' title='Business Process Improvement'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-3944149668277862052</id><published>2006-10-26T08:13:00.000-07:00</published><updated>2006-10-26T08:18:16.494-07:00</updated><title type='text'>Fun in Omaha</title><content type='html'>Having a great time this morning at the &lt;a href="http://www.heartlanddc.com/"&gt;Heartland Developer's Conference&lt;/a&gt; at the Qwest Center in Omaha Nebraska. Later today I'll be giving a session titled "Real SOA: Implementation and Best Practices" that discusses many of the topics found on this blog along with the experiences of the team over the almost 18 months since I came on board at Compassion as a Solutions Architect.&lt;br /&gt;&lt;br /&gt;In short, the talk is broken into seven sections that highlight mostly what went right but also a little of what went wrong or things we could have done better. Those sections and the major point for each follow:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;#1 Define a Services Platform&lt;/strong&gt;&lt;br /&gt;IT buy-in and support is critical&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;#2 Define Messaging and Schema Standards&lt;/strong&gt;&lt;br /&gt;It’s not just about coding standards&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;#3 Consider Cross Cutting Concerns&lt;/strong&gt;&lt;br /&gt;Build it for the long haul&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;#4 Consider Logging and Monitoring Up Front&lt;/strong&gt;&lt;br /&gt;Loosely coupled messaging is hard to tie together&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;#5 Build a Reference Model&lt;/strong&gt;&lt;br /&gt;Don’t jump in to business development&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;#6 Build a Reusable Framework&lt;/strong&gt;&lt;br /&gt;Budget time to help the rest of the organization&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;#7 Don’t forget business activity monitoring&lt;/strong&gt;&lt;br /&gt;Think about questions that will be asked at the end of the day&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-3944149668277862052?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/3944149668277862052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=3944149668277862052&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/3944149668277862052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/3944149668277862052'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/10/fun-in-omaha.html' title='Fun in Omaha'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115299051748497807</id><published>2006-07-29T09:06:00.000-07:00</published><updated>2006-07-29T17:10:54.176-07:00</updated><title type='text'>Always Learning</title><content type='html'>Last week we rolled out the last release in this year long project that developed and then proved out the service oriented infrastructure. Although we have issues to deal with related to the proper implementation of some of the uses cases (more on that in a later post) I thought I'd take a few minutes to discuss what I think is perhaps one of our biggest lessons learned. &lt;br /&gt;&lt;br /&gt;In designing the contracts for our services we purposely wanted to introduce a layer of abstraction into the contracts so as to avoid creating service interfaces that were too closely tied to the existing enterprise data structure. Of course that's a balancing act since on the one had you need to have enough information represented in the various entity schemas to accurately identify the entity, and on the other hand not include extraneous attributes that serve to clutter the picture. &lt;br /&gt;&lt;br /&gt;What we did well in this process is create the larger logical model where we introduced three high level concepts - Constituents, Needs, and Relationships. The first represents individuals of interest to Compassion, the second are entities whose needs can be satisfied such as a child to sponsor, a fund to donate to, or even an activity like praying for the work of the ministry. Relationships then represent the various connections between Constituents and Needs. For example, a Prayer Relationship is established between a Constituent and a Prayer Need while a Payment Relationship is established between a Constituent and a Child, Project, or Fund Need. This structure served us well because it allowed us to subdivide and represent each action for a constituent with a particular relationship type and more importantly allow our messaging infrastructure in BizTalk to recognize these relationship types and create and farm out work to independent orchestrations through a publish and subscribe model. This is an extensible model so that as new relationships are defined the infrastructure can handle them in a loosely coupled fashion (in fact, we implemented a new kind of action in this release without any modifications at all to the core BizTalk messaging model). So far so good.&lt;br /&gt;&lt;br /&gt;The problem entered because going in we (and by that I mean I) didn't really understand how the logical model &lt;i&gt;within&lt;/i&gt; the Payment Relationship should be defined. In other words, the Payment Relationship being the most complex, it needed a more robust definition at the outset in order to handle all of its variance. Unfortunately we rolled out the first definition of the Payment Relationship schema in our previous release when we were dealing only with relatively simple relationships that did not involve funded donations and commitments (in other words, we were dealing only with promises to pay and not persisting and handling rules for credit card and ACH transactions). And while there were place holders in the schema for this kind of information in the first version, the basic structure didn't extend as well as expected to handle this extended information. As a result, and here is the big idea, we ended up adding attributes to the schema that were too closely tied to the existing relational data model. To put it simply, too many codes right out of the database and not enough abstraction between the messaging model and the persistence layer. What happens when you do this of course is that you not only bring along the codes but their interrelationships and dependencies as well. Had we done more analysis up front, we would have seen these relationships and probably created higher level abstractions to handle them within our service contracts.&lt;br /&gt;&lt;br /&gt;In one sense I'm glad we could roll out such a sophisticated system in a series of four iterations over a year, but in another the architectural tradeoffs that resulted from this approach (since we did not have the resources nor the time to fully flush this out ahead of time) will likely hamper us in ways as move down the road. But then again you're always living and learning and so we've toyed with the idea of version 2 service operations in some cases that provide these higher level abstractions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115299051748497807?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115299051748497807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115299051748497807&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115299051748497807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115299051748497807'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/07/always-learning.html' title='Always Learning'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115256413633650578</id><published>2006-07-10T13:25:00.000-07:00</published><updated>2006-07-10T13:42:16.350-07:00</updated><title type='text'>Transitioning</title><content type='html'>For our project we're now about to release our final deliverable. This is the fourth deliverable in the project with the first one being in August of last year. This one is the largest and is used to automate many of the financial transactions performed on our web site which will in turn be used in the automation of requests that come from other channels (scanned forms and external call centers). &lt;br /&gt;&lt;br /&gt;That said, the frameworks that the team has built are about to be used by other project teams as well. To that end one of the talks I attended at TechEd was a discussion of on assisting other developers in using framework that you build. One of the points made was that when you’re developing frameworks (like we have for services, orchestrations, and human workflow) the level of effort for framework developers doesn’t necessarily go down over time if you continue to refine it. The illustration used was the following graph.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/frameworks.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/2568/246/320/frameworks.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As a result, the next effort for the team will be to transition from a project team doing business development into a team that continues to refactor and improve the frameworks that other developers use. &lt;br /&gt;&lt;br /&gt;One of the other points made, however, was that teams should invest the time in the framework up front in order to make it consumable through the use of code generation, templates, etc. The presenter specifically mentioned that trying to put something together in a just in time fashion when other teams need it doesn’t work well in his experience. Unfortunately, because of the very tight schedule we've been on the past year that is largely where we are. The key insight for other teams doing this kind of work is to budget the time (I know how difficult that is when the work is viewed as "overhead" of course) in each release to refactor your frameworks and (reference architecture) and incorporate guidance as you go as well as allow time for mentoring other teams.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115256413633650578?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115256413633650578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115256413633650578&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115256413633650578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115256413633650578'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/07/transitioning.html' title='Transitioning'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115039084315218203</id><published>2006-06-15T09:50:00.000-07:00</published><updated>2006-07-29T17:11:46.180-07:00</updated><title type='text'>Encryption Handler</title><content type='html'>As &lt;a href="http://realsoa.blogspot.com/2006/05/message-security.html"&gt;promised awhile back&lt;/a&gt; we'll take a look at the EDAF handler we created in order to encrypt and decrypt data within our messages.&lt;br /&gt;&lt;br /&gt;To do so we built the handler in an assembly called Compassion.Services.EDAF.Handlers.Security.dll. This is an AtomicHandler (it doesn't hold state between invocations) that can be configured either in the before or after pipeline of service action calls in order to encrypt or decrypt messages using various key providers. &lt;br /&gt;&lt;br /&gt;For example, the configuration of the handler in the ProcessConstituentRequest façade pipeline in order to encrypt messages before they are saved in the ConstituentRequest and ServiceManager databases. &lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;before&amp;gt;&lt;br /&gt; &amp;lt;handler handlerName="MessageEncryptor"&amp;gt;&lt;br /&gt;  &amp;lt;ci:loggerSettings localValue="US" &lt;br /&gt;    keyDir="C:\CompassionServices\Config\      &lt;br /&gt;     Keys\CIPublicOnlyKey.xml" &lt;br /&gt;    operation="Encrypt"  &lt;br /&gt;    message="Request"  &lt;br /&gt;    provider=&lt;br /&gt;      "Compassion.Services.Security.Common.KeyFileProvider,&lt;br /&gt;    Compassion.Services.Security.Common, &lt;br /&gt;    Version=1.0.0.0, Culture=neutral, &lt;br /&gt;    PublicKeyToken=7674363010ccf400" /&amp;gt;&lt;br /&gt; &amp;lt;/handler&amp;gt;&lt;br /&gt;&amp;lt;/before&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;As you can see the handler is configured in the before pipeline and is set to encrypt the Request message using the KeyFileProvider. The handler uses reflection to load the key provider dynamically and pass in constructor arguments such as the file path and asymmetric algorithm. At this time the handler hard codes the instantiation of the RSACryptoServiceProvider since it is the only AsymmetricAlgorithm implemented in v1.1 of the .NET Framework. &lt;br /&gt;&lt;br /&gt;In order to encrypt data on the way out of a service call (for example for an operation that selects payment data the handler would be configured like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;after&amp;gt;&lt;br /&gt; &amp;lt;handler handlerName="MessageEncryptor"&amp;gt;&lt;br /&gt;  &amp;lt;ci:loggerSettings localValue="US" &lt;br /&gt;   keyDir=&lt;br /&gt;     "C:\CompassionServices\Config\Keys      &lt;br /&gt;      CIPublicOnlyKey.xml" &lt;br /&gt;   operation="Encrypt"  &lt;br /&gt;   message="Response"  &lt;br /&gt;   provider=&lt;br /&gt;    "Compassion.Services.Security.Common.KeyFileProvider,&lt;br /&gt;   Compassion.Services.Security.Common, &lt;br /&gt;   Version=1.0.0.0, Culture=neutral, &lt;br /&gt;   PublicKeyToken=7674363010ccf400" /&amp;gt;&lt;br /&gt; &amp;lt;/handler&amp;gt;&lt;br /&gt;&amp;lt;/after&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;One of the interesting things about the implementation of this handler is that the ObjectEncryptor deals with objects whereas EDAF pipelines pass XmlDocument instances to their handlers via the Execute method. As a result, the handler is responsible for pulling the type information out of the EDAF configuration file and using it deserialize the type and pass it to the encryptor. &lt;br /&gt;&lt;br /&gt;In the previous post on this topic a reader asked why we didn't use WS-Security in order to encrypt the message. That's a great question and the answer is that if we had used WS-Security we could certainly have encypted the message body but this would not have allowed us to view the message when it was logged in our infrastructure. In other words, we want visibility into the all parts of the message except those explicitly marked as needing protection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115039084315218203?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115039084315218203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115039084315218203&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115039084315218203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115039084315218203'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/06/encryption-handler.html' title='Encryption Handler'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115029126094135053</id><published>2006-06-14T05:40:00.000-07:00</published><updated>2006-06-14T07:21:34.780-07:00</updated><title type='text'>ESBs and Microsoft</title><content type='html'>Day four at TechEd and spent this morning in a session on "Developing the Next Generation ESB on the Microsoft Platform" which was a case study of sorts of a project donw at Kaiser Permanente. &lt;br /&gt;&lt;br /&gt;They (three speakers shared the podium) started the talk with a discussion of just what is an Enterprise Service Bus? A 2006 survey found the following characteristics as most important:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Message Broker&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Message Transformation Service&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Message Validation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Message-Oriented Middleware&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;The Microsoft speaker then noted that given this list Microsoft will not come out with an "ESB product" because they feel their products are already a superset of the tools required with BizTalk, VS, MSMQ, SQL Server, Host Integration Server, and MOM, along with the guidance they are putting out. &lt;br /&gt;&lt;br /&gt;What was interesting about the talk, highlighted by &lt;a href="http://geekswithblogs.net/bloesgen"&gt;Brian Loesgen&lt;/a&gt;, was that for this particular solution that can be used to literally connect thousands of applications, they created a Core ESB Engine that features an envelope (schema) that specified at the meta data level the kind of message entering the ESB as well as what needed to be done with it. From there they dynamically performed both mapping and runtime endpoint resolution (routing). In other words the architecture supported adding new maps and new endpoints without recompiling or redeploying any part of the ESB. In addition they developed a message oriented approach to exception handling whereby developers publish exception messages and handlers (for example SharePoint) subscribe to them. This allows for highly targeted process-specific handlers to be created for custom exception recovery operations. &lt;br /&gt;&lt;br /&gt;The final speaker from Kaiser highlighted the client and server integration modules (CIM and SIM) that they use to provide abstraction for clients and servers with regards to policy, location, management, security, etc. The CIM is analgous to our Service Agent Framework while the SIM is used for interoperability as well since they support both SOAP invocation of services as well as the use of BizTalk adapters and other custom mechanisms. He also briefly showed their management console they can use to monitor services and develop SLAs. &lt;br /&gt;&lt;br /&gt;Now obviously an organization &lt;i&gt;could&lt;/i&gt; build an ESB in this way and the architecture seems more than solid. The problem, and why an organization might be driven to &lt;a href="http://webservices.sys-con.com/read/47274.htm"&gt;adopt another vendor&lt;/a&gt;, is that this solution was developed with the help both of Microsoft and a systems integrator at I'm sure a significant cost in terms of time and money. For smaller organizations or those that can't invest the time required to develop such a solution going to these lengths is not really an option.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115029126094135053?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115029126094135053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115029126094135053&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115029126094135053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115029126094135053'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/06/esbs-and-microsoft.html' title='ESBs and Microsoft'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115022795364217580</id><published>2006-06-13T12:40:00.000-07:00</published><updated>2006-06-13T12:45:53.653-07:00</updated><title type='text'>Services on CF</title><content type='html'>Attended a session on the .NET Compact Framework 2.0 this afternoon. I haven't looked at CF since I came to Compassion over a year ago and so I was quite disappointed to discover that the System.Configuration namespace is not implemented in the new version. For us this is problematic since our Service Agent Framework relies on &lt;code&gt;IConfigurationSectionHandler&lt;/code&gt; in order to read information about the service agent types, mock messages, and logging that the framework does on the client.&lt;br /&gt;&lt;br /&gt;As a result, if we want to expose our services to mobile clients we'll need to write a Mobile Service Agent Framework that relies on custom XML configuration files as described in the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321197887/qid=1095186998/sr=8-1/ref=sr_8_xs_ap_i1_xgl14/104-7350429-9787116?v=glance&amp;s=books&amp;n=507846"&gt;book I wrote with Jon Box back in 2003&lt;/a&gt;. We can't simply use a web reference proxy since we also rely on custom SOAP headers that the proxy does not create.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115022795364217580?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115022795364217580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115022795364217580&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115022795364217580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115022795364217580'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/06/services-on-cf.html' title='Services on CF'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115021749054090263</id><published>2006-06-13T07:43:00.000-07:00</published><updated>2006-06-13T09:51:30.646-07:00</updated><title type='text'>Pragmatic Architecture</title><content type='html'>&lt;em&gt;"Pragmatism urges us to look to the consequences of what we do, which the discipline of architecture infused with an idealistic focus on intentions frequently resists"&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Attended a pretty entertaining presentation titled "Pragmatic Architecture" by Ted Neward and Cathi Geri. Because the room was heavily populated with architects they had this humorous definition of just what an architect is:&lt;br /&gt;&lt;br /&gt;An architect is someone who...&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Defines architecture&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gets paid more than real developers do&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Focuses on issues that have nothing to do with real-world problems&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Thinks in terms of code not clouds&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Lost the respect of developer friends &amp; teammates&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Speaks with big words and power point slides&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Has upper management fooled&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;But more seriously they went on to talk about the roles or personas that architects take on which include Infraastructure, Enterprise, and Solution (responsible for the design of one or more applications or services within an organization and which the remainder of their talk focused on) and &lt;a href="http://blogs.msdn.com/smguest/archive/2005/12/12/503001.aspx"&gt;identified by Simon Guest&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;They then laid out a taxonomy solution architects can use as they think through laying out solutions... &lt;br /&gt;&lt;br /&gt;&lt;li&gt;Communication/Distribution - Patterns of communication such as request/response and the technologies used to move data.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Presentation/Interaction - Style (graphical, console, prgrammatic), implementation, stovepipe vs. composite/mash-up (one front end, many back ends) vs. jewel (many front ends, one backend), and perspectives (user, admin).&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;State Management - Lifetime, "shape" of the state (relational vs. object vs. hierarchical), location (where, access, and transparency)&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Processing - Implementation, concurrent/parallel, transactional&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Resource Management - Locator/registry, discovery (plug-and-play, peer-to-peer), injected, a priori knowledge&lt;/li&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115021749054090263?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115021749054090263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115021749054090263&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115021749054090263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115021749054090263'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/06/pragmatic-architecture.html' title='Pragmatic Architecture'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115020502113421050</id><published>2006-06-13T06:21:00.000-07:00</published><updated>2006-06-13T06:23:41.150-07:00</updated><title type='text'>Evolving to Patterns</title><content type='html'>Day three of TechEd 2006 and this morning I attended a session on "Evolving to Patterns" by James Newkirk. What I found most interesting was his use of the "broken windows" paradigm and its application it to software development (&lt;a href="http://en.wikipedia.org/w/index.php?title=Special:Booksources&amp;isbn=020161622X"&gt;others have done so as well&lt;/a&gt;). For those not familiar, the idea came from an article written by James Q. Wilson called &lt;a href="http://en.wikipedia.org/wiki/Fixing_Broken_Windows"&gt;"Broken Windows"&lt;/a&gt; that appeared in the March 1982 issue of &lt;i&gt;Atlantic Monthly&lt;/i&gt;. In a nutshell, the idea is that human beings tend not to respect that appear to be in a state of disrepair leading to a vicious cycle of further deterioration. The example used by Wilson is that of an apartment building with one broken window that acts as a signal to vandals to break even more. The same idea can be applied to litter and even the accumulation of junk or dishes in the sink in your own house. The lesson is to fix problems when they are small.&lt;br /&gt;&lt;br /&gt;As applied to software development the notion of fixing your broken windows can be distilled into three basic ideas.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Remove Duplication. &lt;/b&gt; Duplicated code is broken code because it encourages sloppiness and thought processes where developers don't look for ways to inject abstraction. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Simplify Your Code. &lt;/b&gt; Code that is difficult to understand from a structural perspective is broken code because developers would rather write something themselves than have to figure out how to refactor existing code to get the job done. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Clarify your Code's Intent.&lt;/b&gt; A corollary to the above is that the intent of the code needs to be clear. Code's whose intent is not clear through the judicious use of comments and naming conventions is broken because it leads to misusing the code or once again the tendency to put that code in a virtual black box that is not to be touched which leads to duplication.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;And of course evolving your code to use patterns helps us to design code that is ready to handle the changes that will inevitably come.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115020502113421050?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115020502113421050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115020502113421050&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115020502113421050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115020502113421050'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/06/evolving-to-patterns.html' title='Evolving to Patterns'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-115013203519732690</id><published>2006-06-12T10:04:00.000-07:00</published><updated>2006-06-12T10:07:15.220-07:00</updated><title type='text'>Moving to Agile</title><content type='html'>Well, day two at &lt;a href="http://www.microsoft.com/events/teched2006/default.mspx"&gt;TechEd 2006 in Boston&lt;/a&gt; and just came out of a talk on implementing agile methodologies in your organization. What I found interesting is that many of the best practices the speakers (from the patterns and practices group) discussed were ones that our project team are currently implementing. As a result, it was a good check for us in seeing what we have yet to tackle both from a team and organizational perspective. Briefly, here are a few of the practices mentioned and what we've done:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Building a team space.&lt;/b&gt; While our team members still have cubes, 90% of their work is done in a conference room dedicated to the project. In my view, that has increased the speed of communication and helps us to resolve issues more quickly. It also has the effect of allowing everyone to be more or less on the same page with how things are implemented in areas that they perhaps are not currently working in.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;15 minute rule. &lt;/b&gt; Essentially this rule says that if you are blocked for 15 minutes, give up and go ask. The team space definitely encourages this behavior although we haven't talked about it specifically. The corollary to this is that when someone asks for help you can't say no. In our organization this doesn't tend to be a problem anyway but surfacing the need to keep the communication open is key.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Real-time code review, aka Pair Programming. &lt;/b&gt; We don’t pair program today but we do have some overlapping of assignments with two core BizTalk developers and two services devs. In some cases they work together on a feature and of course I assist and help talk through the implementation of code. We should perhaps be more intentional about this.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Give team time to gel. &lt;/b&gt; One of the things that has helped us be successful is that our team had a two month time period in which we implemented a reference architecture before turning our attention to actual production code. As a result, we were able to find our roles before the pressure ramped up. While not intentional, to me, this turned out to be a very helpful by product of the process.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Get a coach or mentor. &lt;/b&gt; None of the team had had much exposure to agile methods before and could have used a bit of coaching before the project commenced. That said, we're not really officially doing agile within Compassion and so this probably wasn't an option. But if we had to do it again, a bit more knowledge would have been useful.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Encourage questions and discussion. &lt;/b&gt; The team space really makes this possible. It tends to keep the environment open and questions are often raised within the room to no one in particular. To me, that's a sign that people are comfortable with each other and no one is too intimidated to ask.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Stack rank work by importance to customer. &lt;/b&gt; While our customers have been very involved in the project, they have only stack ranked work related to hot fixes once various releases have gone into production. Our organization has some way to go it seems before customers are entrusted to do this. The corollary to this is reevaluating that stack frequently. This also needs some work.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Developer estimates are not to be trusted. &lt;/b&gt; The speakers were adamant that developer estimates of more than three days are probably essentially guesses. Unless you can break down a feature into very small tasks, then you're not really estimating. Our developer estimates are a bit larger than that and so we probably have some work to do.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Clarify Customer Requirements. &lt;/b&gt; We have used use case documents and a feature matrix in order communicate the requirements. Unfortunately, the documents are not always as clear as they could be largely because the conceptual model used in the development of the use cases was not familiar to the developers or the users. Had we to do it again, the use cases would be written in the language of the users and not in the language of the logical model. The team would then be responsible for translating that language into a new model used to implement the software. The speakers also note that automated tools should be evaluated that allow the requirements to be executable.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Customer (or their proxy) has to be available. &lt;/b&gt; One of the strengths of our project is that the business users and stake holders almost all reside in the same building and we have had for the most part a business analyst that does a great job of communicating. That allows the team to surface an issue and get feedback very quickly. The average turnaround time is something like four hours. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Implement the 3 strikes rule. &lt;/b&gt; In a nutshell this means you don't refactor code until you have three consumers for it. This has been a balancing act for our team since most of what we're building is being done for the express purpose of reuse across future projects. However, the features within the services we build we evaluate and implement based only on the certainty that they will be reused. In other words, our strategy has been to implement the infrastructure that will allow us to refactor when necessary but not to over-engineer in the near term. Examples include the business rules infrastructure we've implemented as well as the exception reporting and suppression techniques we've used. Interestingly, they noted that when you need to refactor, one technique to allow developers to integrate it into the project is to position it as "making room" for a feature before implementation. Their point is that the term "refactoring" implies rework which signals a red flag among some. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Insist on clarity of code. &lt;/b&gt; As with most agilists, their emphasis was on code readability for maintenance and refactoring. We insist on NDoc comments and code standards in terms of naming conventions etc. to assist with this but should probably be even more diligent about this. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Reward individuals for team behavior. &lt;/b&gt; Our team celebrates success after releases and there is very little in the way of individual rewards. The goal is to get the team to own the entire pie and not just their little piece of it. In that regard, something we do need to work on is the concept of developers working on features and not owning them. We tend to segment our devs into three buckets and each bucket's owns a set of features. While to some extent it is very difficult for everyone to know everything, we should do a better job of specifically asking devs to make changes in code that they have not had a hand in developing. This would increase team ownership.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Everyone is entitled to participate. &lt;/b&gt; In our team room we include not only devs but also testers, the project manager, infrastructure support, and technical writing. Including everyone certainly helps with communication issues but the speakers were actually suggesting that these other disciplines take part in real-time code reviews and design sessions. Each person would then contribute at their level. We certainly have not done this explicitly but again, having everyone in the room provides them accessibility to those discussions. At the end of the project we also do lessons learned off site sessions where we collect feedback to help us improve the process going forward.&lt;/li&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-115013203519732690?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/115013203519732690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=115013203519732690&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115013203519732690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/115013203519732690'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/06/moving-to-agile.html' title='Moving to Agile'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114919246173011837</id><published>2006-06-01T13:04:00.000-07:00</published><updated>2006-06-01T13:07:41.743-07:00</updated><title type='text'>Compassion International Back on Television</title><content type='html'>For those who aren't aware of what Compassion does, there will a TV program airing soon. You can find a list of stations and times &lt;a href="http://www.compassion.com/sponsordonor/CompassionTVshowschedule"&gt;here&lt;/a&gt;. The following is the press release sent out a few days ago. &lt;br /&gt;&lt;br /&gt;From a technical perspective we're interested in seeing how well our service oriented infrastructure handles the additional anticipated load so stay tuned.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;COLORADO SPRINGS, CO, May 30, 2006&lt;/strong&gt; – Beginning June 1, Compassion International is breaking back into the television scene. Compassion will air a 30-minute television special in major markets throughout the United States. Hosted by contemporary Christian music artist Rebecca St. James, the special will focus on Compassion’s child sponsorship program. &lt;br /&gt;&lt;br /&gt;In the 1980s, Compassion was a pioneer among Christian ministries in using television programming, but rising costs eventually led to discontinuing this venue. Today, with hundreds of television channels available, this venue has again become a cost-effective way to share the message of children in poverty.&lt;br /&gt;&lt;br /&gt;“This television special creates a wonderful opportunity to share the needs of children in poverty around the world with many people throughout the United States who may never have heard Compassion’s message before,” said Rick Davis, Compassion’s Director of Marketing. “Our hope is that by telling Compassion’s story through a new venue we will help thousands of people to make a difference in the life of a child in need.”&lt;br /&gt;&lt;br /&gt;The television special is co-hosted by Tim Glenn, Compassion’s U.S. Advocacy Director, and also features nationally renowned author and speaker Tony Campolo and Hollywood actors Victoria Jackson and Cary Elwes. All participants in the special sponsor children of their own through Compassion’s child sponsorship program.&lt;br /&gt;&lt;br /&gt;A complete listing of airtimes can be found on Compassion’s Web site. Visit &lt;a href="http://www.compassion.com"&gt;www.compassion.com&lt;/a&gt; and click on the link to the television program.&lt;br /&gt;&lt;br /&gt;Compassion International is one of the world’s largest Christian child development organizations, working with more than 65 denominations and thousands of indigenous church partners in Africa, Asia, Central and South America and the Caribbean. Since 1952, Compassion has touched the lives of more than one million children.&lt;br /&gt;&lt;br /&gt;It has been recognized for its financial integrity with top ratings and recommendations by several of the nation’s leading not-for-profit “watchdog” organizations. Recently Compassion was recognized by Charity Navigator for its fifth consecutive four-star rating, putting it in the top one percent of 5,000 charities.&lt;br /&gt;&lt;br /&gt;For information about sponsoring a child, contact Compassion online at &lt;a href="http://www.compassion.com"&gt;www.compassion.com&lt;/a&gt; or by calling (800) 336-7676, Monday through Friday, 8 a.m. to 5 p.m., MST.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114919246173011837?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114919246173011837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114919246173011837&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114919246173011837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114919246173011837'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/06/compassion-international-back-on.html' title='Compassion International Back on Television'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114686252479387227</id><published>2006-05-05T13:51:00.000-07:00</published><updated>2006-05-05T13:55:24.793-07:00</updated><title type='text'>1,000,000 Invocations</title><content type='html'>On April 25th our service oriented infrastructure recorded it's one millionth service call since our first deliverable rollout in August of 2005. I'd have to say that the combination of Windows Server 2003, IIS, SQL Server 2000, EDAF, and our own EDAF customizations (handlers and modifications to adapters) have provded to be remarkably stable. During that time we've been able to handle almost 40,000 business transactions during that time frame and most importantly automatically handle upwards of 65% of them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114686252479387227?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114686252479387227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114686252479387227&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114686252479387227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114686252479387227'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/05/1000000-invocations.html' title='1,000,000 Invocations'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114686222846037825</id><published>2006-05-05T13:28:00.000-07:00</published><updated>2006-05-05T13:50:28.486-07:00</updated><title type='text'>Message Security</title><content type='html'>As we gear up for the final deliverable (code-named Bread &amp; Butter) of our project, one of the requirements we've implemented is message security.&lt;br /&gt;&lt;br /&gt;Essentially, in this deliverable we'll be dealing with financial information and in order to comply with the &lt;a href="https://sdp.mastercardintl.com/pdf/pcd_manual.pdf"&gt;Payment Card Industry Data Security Standard&lt;/a&gt; we need to be able to protect credit card and bank account information. This is also a part of a larger security initiative within the organization whereby data elements are tagged with a protection level and treated accordingly and includes the deployment of a PKI (public key infrastructure) solution.&lt;br /&gt;&lt;br /&gt;Although that initiative is not yet in full swing we've implemented the ablility within our services to tag specific schema elements and attributes as requiring protection and then encrypting and decrypting those elements and attributes using public key cryptography.&lt;br /&gt;&lt;br /&gt;Our solution includes the following components:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Encryption components&lt;/strong&gt; – these are set of common components with a pluggable interface that allows for the encryption and decryption of fields and properties within .NET objects using public key encryption (in our first release just RSA is supported).&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Message Encryption Handler&lt;/strong&gt; – an &lt;a href="http://realsoa.blogspot.com/2005/09/selecting-edaf.html"&gt;EDAF handler&lt;/a&gt; that can be used to encrypt or decrypt messages sent to and from services&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;In the remainder of this post we'll look at the encryption components.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Encryption Components&lt;/strong&gt;&lt;br /&gt;The set of encryption components we've built are implemented in two assemblies named Compassion.Services.Security.Attributes.dll and Compassion.Services.Security.Common.dll. The types that are implemented in the two assemblies are discussed below.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Compassion.Services.Security.Attribute&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;This assembly contains the following types.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;ProtectedDataAttribute &lt;/strong&gt;class – this attribute can be used to decorate fields or properties within an object like so.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;[ProtectedData(EncryptionFormat.Inline)]&lt;br /&gt;public string AccountNumber;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;EncryptionFormat &lt;/strong&gt;enumeration – this enumeration is used to specify which encryption technique will be used to encrypt the data within the field or property marked with the attribute. Valid values include Inline and XMLEnc. Inline has been implemented in this release and will specify that data is encrypted directly within the parent element as in the following example.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&amp;lt;CreditCardPaymentSourceData&amp;gt;&lt;br /&gt; &amp;lt;CardholderName&amp;gt;Daniel Ducat&amp;lt;/CardholderName&amp;gt;&lt;br /&gt; &amp;lt;ExpirationDate&amp;gt;2007-03-31T00:00:00.0000000-07:00&amp;lt;/ExpirationDate&amp;gt;&lt;br /&gt; &amp;lt;AccountNumber&amp;gt;AkxcG3qHALhDzqd+5Gxrod1tb2q7V8tYQ5MyJxfk/oFd+J0HkPPM&lt;br /&gt;    +J67hMfq2XMgw97kmuDKqnlhiGA7KE3SNkLNAkvmPMwuWUCn7djOEPLKHb+7MDkN&lt;br /&gt;    4JAX2rIGvgr0N1etazudfegNtGRg3fhLp2Nl8lTD8O/KY5gHVA051mU=&lt;br /&gt; &amp;lt;/AccountNumber&amp;gt;&lt;br /&gt; &amp;lt;CardType&amp;gt;Visa&amp;lt;/CardType&amp;gt;&lt;br /&gt; &amp;lt;Description&amp;gt;****1111&amp;lt;/Description&amp;gt;&lt;br /&gt;&amp;lt;/CreditCardPaymentSourceData&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The value XMLEnc will be used to specify that the &lt;a href="http://www.w3.org/TR/xmlenc-core/"&gt;W3C XML Encryption Syntax and Processing specification&lt;/a&gt; will be used For example, that specification allows for the encryption of individual elements like so:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;&amp;lt;PaymentInfo xmlns='http://example.org/paymentv2'&amp;gt;&lt;br /&gt;  &amp;lt;Name&amp;gt;John Smith&amp;lt;/Name&amp;gt;&lt;br /&gt;  &amp;lt;CreditCard Limit='5,000' Currency='USD'&amp;gt;&lt;br /&gt;    &amp;lt;Number&amp;gt;4019 2445 0277 5567&amp;lt;/Number&amp;gt;&lt;br /&gt;    &amp;lt;Issuer&amp;gt;Example Bank&amp;lt;/Issuer&amp;gt;&lt;br /&gt;    &amp;lt;Expiration&amp;gt;04/02&amp;lt;/Expiration&amp;gt;&lt;br /&gt;  &amp;lt;/CreditCard&amp;gt;&lt;br /&gt;&amp;lt;/PaymentInfo&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Where the CreditCard element is then encrypted as:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;  &lt;br /&gt;&amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;&amp;lt;PaymentInfo xmlns='http://example.org/paymentv2'&amp;gt;&lt;br /&gt;  &amp;lt;Name&amp;gt;John Smith&amp;lt;/Name&amp;gt;&lt;br /&gt;  &amp;lt;CreditCard Limit='5,000' Currency='USD'&amp;gt;&lt;br /&gt;    &amp;lt;EncryptedData&lt;br /&gt;     xmlns='http://www.w3.org/2001/04/xmlenc#'&lt;br /&gt;     Type='http://www.w3.org/2001/04/xmlenc#Content'&amp;gt;&lt;br /&gt;      &amp;lt;CipherData&amp;gt;&lt;br /&gt;        &amp;lt;CipherValue&amp;gt;A23B45C56&amp;lt;/CipherValue&amp;gt;&lt;br /&gt;      &amp;lt;/CipherData&amp;gt;&lt;br /&gt;    &amp;lt;/EncryptedData&amp;gt;&lt;br /&gt;  &amp;lt;/CreditCard&amp;gt;&lt;br /&gt;&amp;lt;/PaymentInfo&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The .NET Framework 2.0 exposes objects in the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.xml.encryptedxml(VS.80).aspx"&gt;System.Security.Cryptography.Xml namespace&lt;/a&gt; to perform this encryption automatically. In order to implement this in the .NET Framework v1.1 the .NET component that will be implemented must perform the encryption behind the scenes. When we move to .NET 2.0 we’ll likely want to reimplement this class accordingly.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Compassion.Services.Security.Common&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;This assembly contains the following types.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;IAsymmetricKeyProvider &lt;/strong&gt;interface – this interface provides the methods used to retrieve key information and return a class derived from the System.Security.Cryptography.AsymmetricAlgorithm .NET type. The idea here is to abstract the retrieval of key information from the implementation of the encryption so that different providers may be implemented in the future. For example, the PKI project in our organization would provide a PKI server and key information could be retrieved using a provider that implements this interface.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;KeyFileProvider &lt;/strong&gt;class – because there is no PKI infrastructure in place today the provider that was built knows how to retrieve key information from XML files given the AsymmetricAlgorithm to use and a path. Application will configure the paths to the key information and protect those keys using NTFS permissions.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;AsymmetricEncryptor &lt;/strong&gt;class – this class uses the key provider to encrypt and decrypt data and can do so for both strings and byte arrays. This class may be used independently of the ObjectEncryptor by applications.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;ObjectEncryptor &lt;/strong&gt;class – this class uses the AsymmetricEncryptor to encrypt and decrypt objects which have fields or properties marked with the ProtectedDataAttribute. Clients such as the MessageEncryptionHandler we'll discuss in the next post may use this object to encrypt and decrypt messages as in the following example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;RSACryptoServiceProvider aag =&lt;br /&gt;new RSACryptoServiceProvider();&lt;br /&gt;KeyFileProvider kfPublic = new KeyFileProvider(aag,&lt;br /&gt;@"C:\PublicOnlyKey.xml");&lt;br /&gt;ObjectEncryptor.Encrypt(pcr, kfPublic);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Here the client instantiates the asymmetric algorithm to use, passes that into the IAsymmetricKeyProvider (in this case along with the path to the key) and finally uses the Encrypt method of the ObjectEncryptor to encrypt the object. Since the object is passed by reference the object will contain the newly encrypted data. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;Next time we'll look at the handler we implemented so that service operations can encrypt and decrypt data.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114686222846037825?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114686222846037825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114686222846037825&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114686222846037825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114686222846037825'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/05/message-security.html' title='Message Security'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114442903211450500</id><published>2006-04-07T09:41:00.000-07:00</published><updated>2006-04-07T09:57:12.193-07:00</updated><title type='text'>Services and .NET 2.0</title><content type='html'>At long last I've started to look into porting our various frameworks to version 2.0 of the .NET Framework. &lt;br /&gt;&lt;br /&gt;As a first step I was able to recompile the entire Enterprise Development Application Framework (EDAF) which included our customizations to the web service interface adapter and transaction handler. While I encounter numerous warnings (mostly related to changes in the System.Configuration namespace and how the assembly key file is specified in the project) there were no compilation errors. Next, I compiled our custom handlers (logging, rules, monitoring). All of that worked well so I was able to deploy EDAF to a new server hosting ASP.NET 2.0.&lt;br /&gt;&lt;br /&gt;From there I was able to re-generate all the .NET code from our schemas and then reubild our common classes (such as the DataFactory) and base classes and saw virtually no warning and no errors. Finally, I built the Constituent Management Service that we use to handle sponsor information and deployed it to the server which once again went smoothly.&lt;br /&gt;&lt;br /&gt;From my machine I then used our existing v1.1 Service Agent for the Constituent Service to make a call to the SelectConstituent operation. Moving forward this is the way our main clients including BizTalk orchestrations and the Ultimus BPM Studio will be consuming the services. &lt;br /&gt;&lt;br /&gt;It worked! &lt;br /&gt;&lt;br /&gt;From here it's just a matter of checking functionality for the various operations but it looks very promising thus far.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114442903211450500?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114442903211450500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114442903211450500&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114442903211450500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114442903211450500'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/04/services-and-net-20.html' title='Services and .NET 2.0'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114442210796373583</id><published>2006-04-07T07:38:00.000-07:00</published><updated>2006-04-07T09:40:18.886-07:00</updated><title type='text'>Exception Handling and Suppression</title><content type='html'>One of the interesting architectural issues we had to grapple with when developing our service oriented infrastructure was how to handle exceptions from our services. &lt;br /&gt;&lt;br /&gt;Obviously one simple approach would simply have been to throw .NET exceptions from our service code in EDAF and then allow ASP.NET to translate that into a SOAP fault. However, this approach does not allow us to differentiate between business (the child you chose to sponsor is no longer available) and system (the database was down) exceptions, does not allow us to add additional information to the exception, does not allow for the return of relevant information in the main body of the response along with the exception, and does not allow overriding of certain exceptions.&lt;br /&gt;&lt;br /&gt;To handle these issues we designed an Exception schema that looks as follows.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;xs:schema&lt;br /&gt;xmlns="http://schemas.compassion.com/common/&lt;br /&gt;exceptions/2005-03-01"&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="Exceptions"&amp;gt;&lt;br /&gt;   &amp;lt;xs:complexType&amp;gt;&lt;br /&gt;     &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;       &amp;lt;xs:element minOccurs="1" maxOccurs="unbounded" &lt;br /&gt;             name="Exception"&amp;gt;&lt;br /&gt;         &amp;lt;xs:complexType&amp;gt;&lt;br /&gt;           &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;             &amp;lt;xs:element minOccurs="1" maxOccurs="1" &lt;br /&gt;             name="DateTimestamp" type="xs:dateTime"/&amp;gt;&lt;br /&gt;             &amp;lt;xs:element minOccurs="0" maxOccurs="1" &lt;br /&gt;             name="Source" type="xs:string" /&amp;gt;&lt;br /&gt;             &amp;lt;xs:element minOccurs="0" maxOccurs="1" &lt;br /&gt;             name="Code" type="xs:string" /&amp;gt;&lt;br /&gt;             &amp;lt;xs:element minOccurs="1" maxOccurs="1" &lt;br /&gt;             name="Message" type="xs:string" /&amp;gt;&lt;br /&gt;             &amp;lt;xs:element minOccurs="0" maxOccurs="1" &lt;br /&gt;             name="StackTrace" type="xs:string" /&amp;gt;&lt;br /&gt;           &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;           &amp;lt;xs:attribute name="Type" type="xs:string" &lt;br /&gt;             use="required" /&amp;gt;&lt;br /&gt;           &amp;lt;xs:attribute name="Level" type="xs:int" &lt;br /&gt;             use="required" /&amp;gt;&lt;br /&gt;         &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;       &amp;lt;/xs:element&amp;gt;&lt;br /&gt;       &amp;lt;xs:any minOccurs="0" maxOccurs="unbounded" &lt;br /&gt;         namespace="##local" processContents="lax" /&amp;gt;&lt;br /&gt;     &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;     &amp;lt;xs:attribute name="SchemaVersion" &lt;br /&gt;       type="xs:decimal" &lt;br /&gt;       use="optional" /&amp;gt;&lt;br /&gt;     &amp;lt;xs:anyAttribute namespace="#any" &lt;br /&gt;       processContents="lax" /&amp;gt;&lt;br /&gt;   &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt; &amp;lt;/xs:element&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;As you can see this schema looks similar to what you'd find in a .NET exception inherited from System.Exception with the addition of Type and Level as well as the ability to add additional data with the inclusion of the any element and attribute per our &lt;a href="http://realsoa.blogspot.com/2005/10/schema-standards.html"&gt;schema standards&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You'll also note that this schema includes the notion of multiple exceptions through the root Exceptions element that includes one or more Exception elements.&lt;br /&gt;&lt;br /&gt;This schemas is then added to the response envelope schemas for each service operations like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;xs:element minOccurs="0" maxOccurs="1" &lt;br /&gt; ref="ex:Exceptions" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;In this way service actions can populate these exception arrays as they see fit, for example in response to a business violation.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;ExceptionsException exception = &lt;br /&gt; new csc.ExceptionsException();&lt;br /&gt;exception.Type="Business";&lt;br /&gt;exception.Level=0;&lt;br /&gt;exception.Source = System.Reflection.Assembly.&lt;br /&gt;   GetExecutingAssembly().Location;&lt;br /&gt;exception.StackTrace = Environment.StackTrace;&lt;br /&gt;exception.Message = string.Format(&lt;br /&gt; this.ResourceManager.GetString("MultipleAddressesFound"),&lt;br /&gt; correctedAddresses.Length);&lt;br /&gt;exception.Code=this.ResourceManager.GetString(&lt;br /&gt;   "MultipleAddressesFoundCode");&lt;br /&gt;exception.DateTimestamp = DateTime.Now;&lt;br /&gt;this.Exceptions.Add(exception);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The typical service then uses a resource file to retrieve the actual error message based on the &lt;a href="http://realsoa.blogspot.com/2005/12/localizing-services.html"&gt;culture found in the SOAP header&lt;/a&gt;. We also have a base class method that can build one of these exceptions when given a .NET exception. &lt;br /&gt;&lt;br /&gt;You'll notice that the base class also allows for the collection of the exceptions to be tracked using an array list so that the service can simply add the exception to the collection and continue processing. &lt;br /&gt;&lt;br /&gt;The precense of exceptions is what then triggers whether or not the service attempts to rollback any transactions that have started and what the response code will be. This the typical code block we use near the end of our services.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;if (this.Exceptions.Count &gt; 0)&lt;br /&gt;{&lt;br /&gt; //append exceptions&lt;br /&gt; response.Exceptions = this.GetExceptions();  &lt;br /&gt; response.ResponseCode = &lt;br /&gt;  ResponseCode.Failure.ToString();&lt;br /&gt; //invalidate trx.&lt;br /&gt; this.InvalidateTransaction();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Here the exceptions that have been collected get placed into the response object to be serialized back to the caller, the response code is set to Failure (which allows clients to detemrine whether or not they should inspect the exceptions collection since we're not throwing a SOAP fault), and the base class method is called to mark the transaction is being invalid (behind the scenes this method uses an EDAF context property that is read by the transaction handler configured in the pipeline for the business action).&lt;br /&gt;&lt;br /&gt;The second interesting aspect of how this works is the &lt;strong&gt;Level &lt;/strong&gt;attribute. We've added this attribute so that we can tag our exceptions being thrown in the business actions as follows:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Business Critical and System = 0&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Business Overridable = 10&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Business Warning = 20&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Business Informational = 30&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;The idea here is that if a consumer of a service receives a failure response and inspects the exceptions, they have the option of submitting the request again but this time setting an ExceptionSuppressionLevel configured on the envelope of the request message like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;xs:attribute name="ExceptionSuppressionLevel" &lt;br /&gt;  type="xs:int" use="required" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;This attribute will default to 0 as will the level in any exceptions that are created in business actions. &lt;br /&gt;&lt;br /&gt;The consumer will then populate the ExceptionSuppressionLevel on the call and the service will suppress any exceptions at that level or above. &lt;br /&gt;&lt;br /&gt;For example, in the case where one of our UI's wishes to create a constituent and override the non-critical exceptions the call would set the ExceptionSuppressionLevel to 10 and the call might return with a Success response and avoid throwing the exception.&lt;br /&gt;&lt;br /&gt;The interesting aspect of this architecture is that it allows us in the future to have services that return a mix of information including informational messages. Exception Levels 0-20 will implicitly roll back the work of the business action while level 30 never does. Using an integer rather than an enumeration allows us to be flexible as other levels of exceptions arise.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114442210796373583?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114442210796373583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114442210796373583&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114442210796373583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114442210796373583'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/04/exception-handling-and-suppression.html' title='Exception Handling and Suppression'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114244947563159022</id><published>2006-03-15T10:10:00.000-08:00</published><updated>2006-03-15T11:04:35.666-08:00</updated><title type='text'>Sponsoring Children and the SOA</title><content type='html'>Last Friday morning the third release (the first two were at the end of August and middle of December) of our SOA-related project, &lt;a href="http://realsoa.blogspot.com/2006/02/dill-is-near.html"&gt;code named "Dill"&lt;/a&gt; went into production.&lt;br /&gt;&lt;br /&gt;For me, the most exciting aspect of the release is that we are beginning to automate the linking of sponsors with children they wish to sponsor by selecting the child on the web. Our system runs a variety of verification rules on both the child and the sponsor (surfaced through operations of a "Need Management Service" where a child is logically defined as a "Need"). If the service operations flag issues that need to be resolved (for example, the child's curernt photo is not available or their biography hasn't been updated) we then send the request to Ultimus where a member of Compassion's Commitment Team can resolve it.&lt;br /&gt;&lt;br /&gt;Thus far the system is running smoothly and the team has not seen any systems exceptions (which we define as exceptions thrown by services that are unhandled and therefore end up in a System Exception queue in Ultimus and can be retried once the issue has been corrected).&lt;br /&gt;&lt;br /&gt;Today, the team is meeting off-site to discuss lessons learned from this release and review the use case documentation for later releases.&lt;br /&gt;&lt;br /&gt;The two biggest issues we had with this release were that...&lt;br /&gt;&lt;br /&gt;1) the release encompassed two different business areas which meant the development of BizTalk orchestrations and service operations for both tracks simultaneously. As a result we had two BizTalk developers and two service developers working on their separate tracks. However, we have one Ultimus subject matter expert (SME) and one database development SME who were stretched pretty thin. Not to mention me on the architecture side of the house trying to juggle the technical and business requirements for both sides (which I didn't always do very well). As a result, during the user acceptance testing we logged 52 issues: 21 were coding errors, 1 was a configuration error, 10 were related to missing business requirements, and 20 were missing development requirements (meaning that the business process was understood but all the details were not communicated to developers, mostly my responsibility)&lt;br /&gt;&lt;br /&gt;2) we changed a few of the core components, for example our controller orchestration that manages the long running business transaction and fixed issues with correlation which meant that either we deploy all of our components side by side or re-process the requests. We chose the latter since this afforded us the opportunity not to have to retry the system exceptions that were already in the system, clean out all the running orchestrations in BizTalk and incidents in Ultimus, and take advantage of new functionality related to schema changes. &lt;br /&gt;&lt;br /&gt;I wrote a little tool that extracted the core documents from our production environment. When we deployed we had 836 current requests in the system and so we used the tool to export these documents (in production we have tracking turned on for this document type).&lt;br /&gt;&lt;br /&gt;The core of the code for this tool uses WMI to retrieve the documents and save them to a directory. The UI is very simple and asks for the name of an orchestration for which to extract messages and a path where the documents are saved.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;int status = 0;&lt;br /&gt;string statusSQL = string.Empty;&lt;br /&gt;string ServiceName = txtOrchestration.Text;&lt;br /&gt;int i = 0;&lt;br /&gt;&lt;br /&gt;switch (cbStatus.SelectedItem.ToString())&lt;br /&gt;{&lt;br /&gt;  case "All":&lt;br /&gt;    break;&lt;br /&gt;  case "Active":&lt;br /&gt;    status = 2;&lt;br /&gt;    break;&lt;br /&gt;  case "Ready To Run":&lt;br /&gt;    status = 1;&lt;br /&gt;    break;&lt;br /&gt;  case "Suspended Resumable":&lt;br /&gt;    status = 4;&lt;br /&gt;    break;&lt;br /&gt;  case "Dehydrated":&lt;br /&gt;    status = 8;&lt;br /&gt;    break;&lt;br /&gt;  case "Completed With Discarded Messages":&lt;br /&gt;    status = 16;&lt;br /&gt;    break;&lt;br /&gt;  case "Suspended Non-Resumable":&lt;br /&gt;    status = 32;&lt;br /&gt;    break;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (status != 0)&lt;br /&gt;{&lt;br /&gt;  statusSQL = " and ServiceStatus = "&lt;br /&gt;   + status.ToString();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ManagementObjectSearcher services =&lt;br /&gt;  new ManagementObjectSearcher(&lt;br /&gt;  "\\root\\MicrosoftBizTalkServer",&lt;br /&gt;  "select * from MSBTS_ServiceInstance where ServiceName='"&lt;br /&gt;  + ServiceName + "'" + statusSQL);&lt;br /&gt;&lt;br /&gt;int docs = Convert.ToInt32(txtMax.Text);&lt;br /&gt;bool done = false;&lt;br /&gt;   &lt;br /&gt;foreach(ManagementObject o in services.Get())&lt;br /&gt;{&lt;br /&gt;  ManagementObjectSearcher mos =&lt;br /&gt;   new ManagementObjectSearcher(&lt;br /&gt;   "root\\MicrosoftBizTalkServer",&lt;br /&gt;   "select * from MSBTS_MessageInstance&lt;br /&gt;    where ServiceInstanceID='"&lt;br /&gt;   + o.GetPropertyValue("InstanceID").ToString()&lt;br /&gt;   + "'");&lt;br /&gt;&lt;br /&gt;   foreach(ManagementObject mo in mos.Get())&lt;br /&gt;   {&lt;br /&gt;     i++;&lt;br /&gt;     mo.InvokeMethod("SaveToFile",&lt;br /&gt;      new object[]{txtPath.Text});&lt;br /&gt;     sbPanel1.Text = "Extracting message "&lt;br /&gt;      + i.ToString();&lt;br /&gt;     if (i == docs)&lt;br /&gt;     {&lt;br /&gt;       done = true;&lt;br /&gt;       break;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if (done ==true)&lt;br /&gt; break;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sbPanel1.Text = "Done. Extracted " + i.ToString()&lt;br /&gt;  + " messages.";&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When the document is extracted BizTalk saves both a .OUT file which contains the XML document and an .XML file which contains the context properties which include our message and message stream ids used in our &lt;a href="http://realsoa.blogspot.com/2005/05/service-communication.html"&gt;custom SOAP headers&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We also then have a tool which uses our &lt;a href="http://realsoa.blogspot.com/2005/05/service-agent.html"&gt;Service Agent Framework&lt;/a&gt; to resubmit these documents. The core of the&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;private void RunIt(FileInfo f)&lt;br /&gt;{&lt;br /&gt;  try&lt;br /&gt;  {&lt;br /&gt;    label1.Text = "Processing " + f.FullName;&lt;br /&gt;    this.Refresh();&lt;br /&gt;&lt;br /&gt;    XmlDocument payload = new XmlDocument();&lt;br /&gt;    payload.Load(f.FullName);&lt;br /&gt;&lt;br /&gt;    XmlNodeList nodes = payload.GetElementsByTagName(&lt;br /&gt;     "ConstituentProcessRequest",&lt;br /&gt;     "http://schemas.compassion.com/constituent/&lt;br /&gt;       processrequest/2005-10-01");&lt;br /&gt;    XmlDocument xdoc = new XmlDocument();&lt;br /&gt;    xdoc.LoadXml(nodes[0].OuterXml );&lt;br /&gt;&lt;br /&gt;    // add the updateable attribute to the profiles&lt;br /&gt;    AddUpdateable(xdoc);&lt;br /&gt;    AddPRType(xdoc);&lt;br /&gt;&lt;br /&gt;    XmlDocument resp = ServiceAgentProxy.ExecuteOperation(&lt;br /&gt;     "Compassion.Services.Agent.&lt;br /&gt;     Constituent.ConstituentServiceAgent",&lt;br /&gt;     "ProcessConstituentRequest",xdoc,Guid.NewGuid().ToString(),&lt;br /&gt;     Guid.NewGuid().ToString(),Guid.NewGuid().ToString(),&lt;br /&gt;     "performance","urn:CPR Load Utility",String.Empty );&lt;br /&gt;  }&lt;br /&gt;  catch (Exception ex)&lt;br /&gt;  {&lt;br /&gt;    listBox1.Items.Add(f.FullName + " " + ex.Message );&lt;br /&gt;    System.Windows.Forms.MessageBox.Show(ex.Message);&lt;br /&gt;  }&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The call to the ExecuteOperation method of the ServiceAgentProxy object submits the document to the service facade (the ProcessConstituentRequest operation of the Constituent Management Service) then then uses MSMQT to submit the document to BizTalk.&lt;br /&gt;&lt;br /&gt;The other interesting thing that this tool does is to modify the documents where appropriate in order to support some of the minor schema changes we made. As a result we wrote couple helper methods that add new attributes to the document where needed.&lt;br /&gt;&lt;br /&gt;We'll then use this tool to submit the 836 requests to the infrastructure over the next few days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114244947563159022?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114244947563159022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114244947563159022&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114244947563159022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114244947563159022'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/03/sponsoring-children-and-soa.html' title='Sponsoring Children and the SOA'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114072557693161727</id><published>2006-02-23T12:01:00.000-08:00</published><updated>2006-02-23T12:12:56.943-08:00</updated><title type='text'>Dill is Near</title><content type='html'>Just a quick update on our project. &lt;br /&gt;&lt;br /&gt;We're currently in the process of performing integration testing in preparation for our next release in early March code-named "Dill". That release will feature the deployment of three new services that contain 13 new service operations implemented as EDAF business actions. Of those one service and two operations are &lt;a href="http://realsoa.blogspot.com/2005/05/tenets-of-service-orientation.html"&gt;Infrastructure related&lt;/a&gt; and provide a service facade for Compassion's internal Consituent Communications Queue (CCQ) system while the other two services and 11 operations are Enttiy Services. Behind those services are two new business processes implemented in BizTalk and three new Ultimus exceptions.&lt;br /&gt;&lt;br /&gt;One of the interesting things I was looking at the other day was that since our first release went into production last fall our services have handled over 625,000 requests, 25,000 of which are business transactions submitted from our web site. Of those 77% are following the happy path and updating our enterprise database automatically.&lt;br /&gt;&lt;br /&gt;Previously 100% of the requests were handled manually and so the combination of web serivces for entity manipulation, BizTalk for business process automation, and Ultimus for human workflow have combined to form an effective tool for automating a portion of Compasison's business which in turn frees our internal employees to perform more strategic activities, and ultimately helps to release children from poverty. To me anyway, that's an appropriate use of technology.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114072557693161727?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114072557693161727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114072557693161727&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114072557693161727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114072557693161727'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/02/dill-is-near.html' title='Dill is Near'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-114072444934363529</id><published>2006-02-23T11:35:00.000-08:00</published><updated>2006-02-23T12:01:00.553-08:00</updated><title type='text'>BizTalk Pipelines in the SOA</title><content type='html'>Here's an interesting problem that occurred on our team that we weren't aware of.&lt;br /&gt;&lt;br /&gt;In our architecture all messages that in and out of BizTalk using custom SOAP headers based on WS-Addressing as I discussed in &lt;a href="http://realsoa.blogspot.com/2005/10/messaging-standards.html"&gt;Message Standards&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What that means is that we implemented a custom pipeline component in C# that parsed our SOAP header and promoted the various fields we use to track messages such as MessageId and MessageStreamId. This pipeline is invoked when messages are received from outside sources such as our human workflow tool, Ultimus BPM Studio which posts to an HTTP receive location.&lt;br /&gt;&lt;br /&gt;In the Exeucte method in our original code we used the following line to get the load the incoming document&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;xmlDoc.Load(inmsg.BodyPart.Data);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This code works fine as long as tracking is turned on in BizTalk. Once we turned off tracking in development we ran into problems where the properties were not being promoted like so:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;There was a failure executing the receive pipeline: &lt;br /&gt;"Compassion.BizTalk.Pipelines.Common.&lt;br /&gt;SOAPHeaderReceivePipeline"&lt;br /&gt;Source: "Compassion.BizTalk.Pipelines.Utilities" &lt;br /&gt;Receive Location: "/UltimusResponse/BTSHTTPReceive.dll" &lt;br /&gt;Reason: Pipeline component exception - Not implemented &lt;/pre&gt;&lt;br /&gt;Through a call to Microsoft (and subsequently through reading things &lt;a href="http://geekswithblogs.net/cyoung/articles/12132.aspx"&gt;like this&lt;/a&gt;) we discovered that we should be using the GetOriginalDataStream method in order to grab the message. This is the case since BodyPart.Data clones the incoming stream and the HTTP adapter uses the network stream which does not support cloning. Turning on tracking allows BizTalk to create a wrapper around the original message. And hence you can use  BodyPart.Data.&lt;br /&gt;&lt;br /&gt;So our new code looks as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Stream s = inmsg.BodyPart.GetOriginalDataStream();&lt;br /&gt;xmlDoc.Load(s);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once we have the incoming message we can run a series of try/catch blocks as follows to grab the elements we need from the SOAP header and promote them.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// strip off the envelope and return &lt;br /&gt;//just what is within the Body&lt;br /&gt;System.IO.MemoryStream ms = new System.IO.MemoryStream&lt;br /&gt;  (Encoding.UTF8.GetBytes(xmlDoc.SelectSingleNode(&lt;br /&gt;   "//*[local-name()='Body']").InnerXml));&lt;br /&gt;inmsg.BodyPart.Data = ms;&lt;br /&gt;    &lt;br /&gt;try &lt;br /&gt;{&lt;br /&gt;  strMessageId = xmlDoc.SelectSingleNode(&lt;br /&gt;   "//*[local-name()='Header']&lt;br /&gt;   /*[local-name()='MessageID']")&lt;br /&gt;   .InnerText;&lt;br /&gt;  // remove the "uddi:" if present&lt;br /&gt;  strMessageId = strMessageId.Replace("uuid:","");&lt;br /&gt;  inmsg.Context.Promote(&lt;br /&gt;   "MessageId", &lt;br /&gt;   "http://schemas.microsoft.com/&lt;br /&gt;   BizTalk/2003/SOAPHeader".ToString(),&lt;br /&gt;   strMessageId);&lt;br /&gt;}&lt;br /&gt;catch {}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-114072444934363529?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/114072444934363529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=114072444934363529&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114072444934363529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/114072444934363529'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/02/biztalk-pipelines-in-soa.html' title='BizTalk Pipelines in the SOA'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113996278137200498</id><published>2006-02-14T16:15:00.000-08:00</published><updated>2006-02-23T11:34:29.940-08:00</updated><title type='text'>VSTS Whys and Hows Part II</title><content type='html'>In the first article in this series I described some of the problems inherent in modern software development and suggested a few ways in which those issues might be addressed by tools like Visual Studio 2005 Team System (VSTS) soon to be released. In other words, the first article addressed the “whys” of VSTS. In this article I’ll tread further on that path by providing an overview of Visual Studio 2005 Team System (VSTS) from a functional perspective so that you can see how VSTS plans to address the problems. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;More than the Sum of Its Parts&lt;/strong&gt;&lt;br /&gt;From a high level, VSTS is composed of five products:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Visual Studio Team Foundation&lt;/em&gt;. This is a server product or platform that exposes features shared by the various clients (as well as Office applications such as Microsoft Excel and Microsoft Project) shown in the diagram. While some of the features exposed by the clients can be used independently, it is Team Foundation that pulls them all together and enables the collaboration and communication so desperately needed by software development teams. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Visual Studio Team Foundation Client&lt;/em&gt;. A client tool geared towards project managers and other non-developers. The Team Foundation Client exposes a subset of the shared features in Team Foundation through the concept of the Team Explorer discussed below. While the Team Foundation Client is based on the Visual Studio IDE it does not include the language features and other tools that developers and architects would use. The Team Foundation Client is the basis for integration in the other products mentioned here.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Visual Studio Team Architect&lt;/em&gt;. The client tool used by software architects to design serviced-oriented solutions and validate their designs against the actual hardware and software environment. Team Architect also includes a modeling tool called the Class Designer that is tightly integrated with code.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Visual Studio Team Developer&lt;/em&gt;. The traditional Visual Studio IDE augmented with a set of features that enable developers to more easily comply with policies and collaborate in a team environment. Although many of the features found in Team Developer such as unit testing and static code analysis can be used without access to Team Foundation in the Visual Studio IDE, the metrics or results that the tools output cannot then be shared with the team. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Visual Studio Team Test&lt;/em&gt;. A client tool for those devoted to testing that enables them to design, manage, and execute manual, unit and load tests. &lt;br /&gt;Each of these products is designed to provide specific features that aid in the process of software development. It is their combined power when adopted by the entire team, however, that allows VSTS to address the core issues teams face of communication, predictability, integration, and process. In the remainder of this article I’ll drill down on each one of the products and walk through its key features so you’ll understand how it fits into the bigger picture.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Visual Studio Team Foundation&lt;/strong&gt;&lt;br /&gt;As we saw in the first article, many of the problems encountered by software development teams arise from lack of communication within the team and lack of integration of the tools used by the team. In VSTS the Team Foundation provides the server platform that enables both communication and integration. In that way Team Foundation can be thought of as the organizing principal in VSTS. And because of its centrality it is worth having a look at its major features.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Change Management&lt;/em&gt;. A brand new (not simply a new version of Visual SourceSafe) source code control infrastructure based on SQL Server 2005 for versioning code and other project deliverables. Built from the ground up for secure and high-speed access, this is a robust version control system that supports advanced features such as branching, change sets, a novel feature called shelving, as well as check-in policies. To give one example of how this feature addresses the problem of integration discussed in the previous article, consider VSTS’s check-in policies. Essentially, when the Project Manager creates the project in VSTS he can associate policies with the check-in of source code. These policies validate that a developer’s changes comply with whatever the organizational requirements are before the set of changes can be checked-in. For example, a check-in policy might be activated so that a developer must run static code analysis or a unit test on his code before checking it in. If the developer fails to do this he’ll receive a policy warning in the Team Developer IDE. If he chooses to ignore the policy the project administrator can optionally be notified through email. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Work Item Tracking&lt;/em&gt;. A centralized repository stored in Team Foundation’s SQL Server 2005 operational data store and used to track tasks, defects, requirements, enhancements and - through the use of custom attributes - anything else required by the project. If Team Foundation is the organizing principal in VSTS, then Work Item Tracking is the central concept within Team Foundation. Requirements, unit tests, test cases, and source code can all be associated with work items to provide the basis for a rich set of metrics collected by the client tools. And as with other aspects of Team Foundation, a set of default Work Item types ships with the product but can be extended by your organization or third parties. Project managers and other team members can interact with work items through Visual Studio Team Foundation Client or even Microsoft Excel and Microsoft Project. Of course, correlating this information with the detailed data collected by the various tools makes for a powerful combination in terms of reporting on the health, status, and direction of the project.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Reporting&lt;/em&gt;. A set of over thirty predefined reports built with SQL Reporting Services used to report on the health and status of the project. These reports can then be made available both on the Team Project Portal and directly within the applications used by the team members through the Team Explorer. Data to produce these metrics is actually collected behind the scenes by the tool in which the team members work as they perform their tasks and then stored in a central SQL Server Analysis Server repository from which the reports are created. For example, data about test execution and results are saved when a tester executes his test cases and data concerning code churn is saved when developers check out and check in code files. This approach has the obvious advantage of freeing Project Managers and other team members from the hassle of data collection and ensures that the data is always fresh. At the same time the data collection process is not intrusive and works within the natural workflow of the team.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Team Project Portal&lt;/em&gt;. To help solve the problems related to collaboration and communication Team Foundation automatically creates a web site or Team Project Portal for each project using a Windows SharePoint Services (WSS) team site. From this portal project stakeholders can get a quick view of the project’s progress both freeing up the time project managers would spend creating status reports by hand and enabling stakeholders to provide input and make course corrections. The portal’s document library is also pre-populated with document templates, for example discovery and requirements specification templates, and sample files for use by team members. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Project Management&lt;/em&gt;. We saw in the first article that teams could benefit from tools that help guide them through the process of software development. In order to provide process guidance VSTS includes the concept of methodology templates which can be thought of as a schema for software project. These templates help to structure the process used by the team by exposing a set of documents, project roles, work item types, a web portal template, policies, and what are called process tasks from within all of the VSTS tools. For teams that have no process a Project Manager can choose one of the predefined methodology templates that will ship with VSTS such as a new version of Microsoft’s Solution Framework called MSFT Agile. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Build&lt;/em&gt;. One of the required activities in a software development project is to actually build the software. To that end a core feature of VSTS exposes a common process for building executables based on the tool Microsoft uses internally called MSBuild. This system is designed to deliver a “build lab in a box” that makes it easier for teams to implement the best practice of daily builds. This tool allows for the creation and execution of automatic builds on a separate build server that integrate different types of tests. As the tests execute data is collected about the builds in the operational and analytical data stores, for example to tie the build number to Work Items and automatically create work items for build failures. &lt;br /&gt;Taken as a whole these features provide a solid platform on which teams can define and implement their software development process.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Team Foundation Client&lt;/strong&gt;&lt;br /&gt;The second product that comprises VSTS is the Team Foundation Client. This can be thought of as a tool that Project Managers and other generally non-technical team members will use. While it runs within the Visual Studio shell, it does not include the overhead of language compilers and modeling features that PMs and other don’t need nor want. &lt;br /&gt;&lt;br /&gt;The services of Team Foundation are exposed in the Team Foundation Client through the Team Explorer. This tool is accessible within all of the different VSTS clients and really provides the foundational access to VSTS.&lt;br /&gt;&lt;br /&gt;The Team Explorer is a tool window that can be hidden similar to the Server Explorer that developers are already familiar with in previous versions of Visual Studio .NET. Through this window team members can easily find work products and data associated with the project&lt;br /&gt;&lt;br /&gt;More importantly the Team Explorer also acts as a launch point into the set of tools that ship with VSTS. By simply navigating to the appropriate node in the Explorer the context of the application changes and allows the team member to create and run reports, query on tasks assigned to them, create custom queries, and view project builds and test results among other activities. No longer is there a need to manually switch between various tools thereby increasing productivity. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Team Architect&lt;/strong&gt;&lt;br /&gt;In the previous article I discussed the scenario where a Solution Architect creates a design only to find out later that it is precluded by the hardware or software configuration of the deployment environment. In order to address these sorts of issues the Team Architect product, in addition to including the Visio UML modeling tools present in the prior version of Visual Studio Enterprise Architect, includes a suite of graphical modeling tools. These tools are designed to allow architects to visually design systems based on service oriented architectures (SOA) and to validate those designs against the actual environments in which they’ll run. &lt;br /&gt;Specifically, the suite of tools includes:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Application Designer&lt;/em&gt;. The Application Designer provides a design surface on which the architect can diagram a set of applications that exchange messages. In other words the Application Designer can be used to create a model of connected applications that are dropped on the design surface and connected via Web Services Description Language (WSDL) contracts. Off the shelf application types include web sites, Windows applications, web services, databases, and BizTalk services as you can see in the toolbox on the left side of the screen.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Logical Data Center Designer&lt;/em&gt;. The Logical Data Center Designer is a designer that an Infrastructure Architect can use to create a logical model of a part of the data center. As such it allows for the creation of “logical servers” that specify the application hosting environment on those servers. For example, a logical server can specify the communications protocols allowed (perhaps on HTTPS) and the types of services that are enabled (IIS, FTP) in addition to the communication between other logical servers and those servers grouped into what are called “zones”. Constraints including security requirements on the logical server can then be specified. The architect can either create the servers himself or read the configuration information from physical machines using the tool.&lt;/li&gt;&lt;br /&gt; &lt;br /&gt;&lt;li&gt;&lt;em&gt;System Designer.&lt;/em&gt; The System Designer provides a design surface used by the architect to create what is referred to as a configured system. A configured system is composed of one or more applications defined in the Application Designer for a particular deployment. The System Designer provides a higher-level view so that architects can visualize how systems will communicate with external systems or with other internal (nested) systems. From there the architect can drill down to the applications if necessary in order to define them. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Deployment Designer.&lt;/em&gt; The Deployment Designer is used by architects to create a deployment for a configured system defined in the System Designer or for an application defined in the Application Designer. Here is where the application and systems models are mapped onto the data center models through a process called binding. Prior to this all the information (metadata) collected by the designers was made available to a constraint engine and as a result validation and consistency checks can be made. If the configuration of an application violates constraints on a logical server, the Task List within Team Architect alerts the architect to the issue, thereby allowing the problem to be corrected before actually attempting a deployment. The Deployment Designer also generates a deployment report visible that can be used to communicate between IT and Operations as well as a deployment script that includes configuration settings and files to be deployed.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Class Designer.&lt;/em&gt; Although not directly connected to the other three tools, the Class Designer provides the architect with a superset of the capabilities of traditional UML static structure or class diagrams. The Class Designer represents the .NET type system with full fidelity and therefore allows architects to be very precise in the design of their classes, structures, enumerations, and interfaces in a way that UML cannot. Indeed, as types are designed on the surface of the Class Designer the code for those types is written in the project. Conversely, changes to the code will be reflected in the model since both the code and model are simply reflections of the SDM. And because design at this level isn’t restricted to architects, the Class Designer is also available in the Team Developer. Obviously, this more connected approach can help to solve some of the communication problems inherent in software development.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Team Developer&lt;/strong&gt;&lt;br /&gt;In many teams today, however, developers are hindered from reaching high levels of productivity by having to cobble together multiple tools in order to adopt development best practices and having to repeatedly context-switch between tools in order to interact with requirements and tasks. When multiplied across all the developers on the team, this in turn drives down the predictability of the entire project. To address problems like these Team Developer includes the Team Explorer mentioned previously. This tool window immediately gives the developer the ability to see which Work Items (tasks) they are responsible for and through its integration with Team Foundation can tie actual work the developer is doing to those work items thereby automatically and continuously updating the project’s status. As you would expect Team Developer integrates with Team Foundation by providing the interface to Team Foundation’s change management (source code control) system and its’ check-in policies discussed previously.&lt;br /&gt;&lt;br /&gt;Team Developer also includes the following tools.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Unit Testing and Code Coverage Analysis&lt;/em&gt;. One of the best practices that Team Developer enables is unit testing and by extension the practice adopted by many agile teams known as Test Driven Development or TDD. Team Developer does this through its inclusion of an attribute-based unit testing framework much like the popular NUnit that is directly accessible within the IDE. Using this framework developers can create unit tests and execute them during the development process while behind the scenes the results are automatically recorded in Team Foundation’s analytical data store. In addition Team Developer enhances its power by coupling it with the testing best practice of code coverage analysis. Using this practice, when a team member executes a unit test not only will the test results be tabulated but optionally the percentage of code executed during the test for each source code module (files, namespaces, classes, methods) can be viewed as well as being stored by Team Foundation for later use.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Static and Dynamic Code Analyzers&lt;/em&gt;. A second best practice that teams often have a harder time getting their developers to adopt is code reviews. When done well, code reviews with other developers and architects provide a structured way to gain feedback in a constructive way that proactively enables the developers to make changes that improve code quality and maintainability. To address this need Team Developer includes both Static and Dynamic Code Analyzers that can be thought of as an automated method of performing code reviews. For example, the static code analysis tool comes preconfigured with a set of warnings that can identify known issues in .NET development involving performance, security, general design, and naming guidelines akin to the FxCop tool in use by many in the .NET developer community. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Code Profiler.&lt;/em&gt; Developers can also increase their productivity through proactively addressing performance problems using tools Team Developer includes. With these tools developers can sample the performance and then instrument their code in order to collect detailed performance statistics to enable drill down on potential problem areas. For example, a developer can use their unit tests to generate a Performance Session where the code is sampled in order to identify potential performance bottlenecks in terms of both throughput and resource usage. From there the developer can instruct the tool to insert timing probes into the desired subset of code to gather more detailed statistics. Finally, a detailed performance report is generated so that developers can decide where to begin further investigation.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Team Test&lt;/strong&gt;&lt;br /&gt;VSTS takes testing a step further than simple unit testing by making them available in the Team Test product geared specifically for testers. This product enables testers to execute the unit tests developers create in a systematic fashion to ensure that code checked in by multiple developers passes previously constructed tests. This is an example of another testing best practice referred to as regression testing.&lt;br /&gt;&lt;br /&gt;Team Test goes even further by making testers first-class citizens of the project by highlighting the importance of testing at the team level through a test authoring and execution environment. That environment includes additional test types such as Web Tests, Load Tests (similar to the tool Application Center Test tool that ships with Visual Studio .NET 2003), Manual Tests, and Ordered Tests and test case management all integrated into Team Foundation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113996278137200498?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113996278137200498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113996278137200498&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113996278137200498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113996278137200498'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/02/vsts-whys-and-hows-part-ii.html' title='VSTS Whys and Hows Part II'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113891073016793611</id><published>2006-02-02T11:55:00.000-08:00</published><updated>2006-02-02T12:19:57.646-08:00</updated><title type='text'>VSTS Whys and Hows</title><content type='html'>As I’m sure many readers are aware by now, Visual Studio developers are about a month away from the second part of the Visual Studio 2005 release that includes a slew of new features that make a developer’s job easier. Visual Studio 2005 Team System.&lt;br /&gt;&lt;br /&gt;In the first of this two part series I’ll describe a few of the specific problems you and your team probably face that served as the impetus for the creation of Visual Studio 2005 Team System (VSTS). In the next article I’ll get down to how VSTS is designed to address these issues. Taken together, the goal of these two articles is not simply to give you a laundry list of VSTS features, but rather to place them in the context of the problems they were designed to address.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Software Development is Hard&lt;/strong&gt;&lt;br /&gt;I don’t want to sound like a grumpy old man who sits in front of the barbershop longing for yesterday while muttering about failures of the modern world, but software development is hard and getting harder.&lt;br /&gt;&lt;br /&gt;Gone are the simpler days of monolithic applications running on a single platform free from deployment issues. Gone are the heady days of client/server computing and the “enterprise data model” accessible through Visual Basic or Powerbuilder apps free from data sharing issues. And even gone are the days of simple data-driven ASP or ASP.NET web applications accessing our data behind our firewall. No, today in our ever more connected world, our solutions require access from multiple platforms, devices (heterogeneity), and networks, data sharing across the enterprise and with business partners (service orientation), and scalability on commodity hardware. All of this in an environment where the driving factors are less time and fewer resources.&lt;br /&gt;&lt;br /&gt;The truth of this trend towards increasing complexity has driven many organizations to consider adopting the more loosely-coupled architectural pattern of service orientation, or a Service Oriented Architecture (SOA), made practical by the implementation and maturation of web services. And as with any architectural shift SOA and web service applications come a new set of design and implementation challenges that developers will need to address.&lt;br /&gt;&lt;br /&gt;I know that this come as no surprise to many of you reading this article - you who have managed, designed, built, and tested complex enterprise solutions requiring heterogeneity, service orientation, and scalability. But I also know that in doing so many of you are looking for tools to make your jobs easier&lt;br /&gt;&lt;br /&gt;So why is software development difficult? In short I see four primary reasons teams struggle to build quality software.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Communication Breakdowns&lt;/strong&gt;&lt;br /&gt;The reality is that in many cases IT teams are today both geographically and functionally distributed. This distribution creates gaps in communication that provide opportunities for issues to be dropped, misunderstandings to arise, and information flow to be slow and haphazard.&lt;br /&gt;&lt;br /&gt;Fortunately as you’ll see in the next article, with VSTS the very technology that makes geographical distribution possible in many cases can also be applied to open up new channels of communication. And of course the benefits of tools enabling better communication aren’t restricted to geographically disparate teams. Even in small and local teams, crucial information is often dispersed and not easy to find or not captured in the first place. Tools that provide a centralized location for all of this information is in many ways the first step towards controlling the project.&lt;br /&gt;&lt;br /&gt;At the same time, as with much of the modern world, the IT industry has tended towards increasing specialization. Although in a small organization you may have to be a jack of all trades, in many organizations silos have developed where expertise in project management is restricted to one group while development resources come from another and solution architectures from a third. Because some of these groups share certain attributes and not others there are differing amounts of conceptual space between these groups as illustrated in Figure 1 where Developers and Testers are more closely related than Solution Architects and Project Managers. This specialization over time has the effect of producing conflicting best practices, architectures, and ultimately a vision for how software should be developed.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/itsilos.0.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2568/246/400/itsilos.0.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;The Proximity of IT Silos&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;As an example of addressing the first need consider the case where a Solution Architect is designing a system all alone, safely ensconced in his architectural silo made of ivory. When his architecture is complete he hands it off to the developers who merrily code away. Job done. Not so fast. When it comes time to discuss how this solution will actually be deployed in production, the Solution Architect is shocked and dismayed to discover that Operations doesn’t support the server or communications configuration he was assuming for his “perfectly architected” solution. And of course Operations derives a certain guilty pleasure in crushing the ivory tower. His solution no longer looks so perfect and he then must rework the architecture or spend political capitol in trying to get the Operations policies changed, costing both time and development resources.&lt;br /&gt;&lt;br /&gt;What our architect needed in this scenario was a tool that helped him map his solution architecture to the existing hardware and software environment including the Operations policy so that he could take it into consideration during his work. In the second article in this series you’ll see how VSTS addresses this problem through a suite of design tools.&lt;br /&gt;&lt;br /&gt;Tools that enable information flow between these groups will go a long ways towards solving communication breakdowns.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Lack of Predictability&lt;/strong&gt;&lt;br /&gt;The Danish physicist Niels Bohr once said that &lt;span style="color:#ffff00;"&gt;“prediction is very difficult, especially about the future”&lt;/span&gt;. I don’t think he had software development in mind but I do think it is applicable. This is borne out intuitively by the concern many have in the IT industry for being able to predict the success of projects. Their concern is not unfounded. As Steve McConnell writes in his 2004 book &lt;em&gt;Professional Software Development&lt;/em&gt;:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color:#ffff00;"&gt;“Roughly 25 percent of all projects fail outright, and the typical project is 100 percent over budget at the point it’s cancelled. Fifty percent of projects are delivered late, over budget, or with less functionality than desired.”&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;Why do these projects end up over budget, late, feature-poor, or cancelled? In most cases it was because their teams couldn’t accurately predict or control the software development lifecycle. And at the heart of enabling better prediction in your projects lies metrics and repeatable practices.&lt;br /&gt;&lt;br /&gt;The simple fact is that teams manage projects according to the metrics they are able to collect. If the metrics collected are the right ones the Project Manager and other stakeholders can quickly get a feel for where the project is headed, to better estimate its completion, and to actually drive it towards completion by analyzing risk and making course corrections when necessary. In addition, a key point that organizations often undervalue is that good (meaning real and not anecdotal) metrics on previous projects rather than personal memory, subjective intuition, or seat of the pants guesswork provide the best input into making estimates on future projects.&lt;br /&gt;&lt;br /&gt;I would suggest that what project teams could use are tools that help them address the area of metrics in at least the following ways:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;By suggesting predefined metrics taken from best practices that have been proven to provide insight into projects such as metrics related to progress towards the schedule, the stability of the plan, code quality, and measuring the effectiveness of testing. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;By offering a single place in which data to produce metrics is stored in order to eliminate the separate silos in which that data is stored today.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;By supporting an automatic way of collecting data in a timely fashion that is integrated into the natural workflow of the team. &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;The second aspect of more accurately predicting the success of software projects lies in the adoption of repeatable or “best” practices. While we all know that one size does not fit all I also know that in almost any endeavor applying a structured or methodical approach reduces the variability in the outcomes.&lt;br /&gt;&lt;br /&gt;Unfortunately, many teams have no set of repeatable or structured practices that they can hang their hats on and they can use to focus their efforts. For these teams, for example, a developer is simply tasked with implementing a feature and then left to his own devices. While some developers may naturally or through intentional analysis apply some set of structured principles to their development, many will not and the result is that the productivity of those developers and hence the predictability of both the software quality and the schedule are almost impossible to get a handle on. This is largely borne out by the oft-repeated finding that developers differ in their productivity on the order of 10 to 1 as noted by McConnell in &lt;em&gt;Professional Software Development&lt;/em&gt;. In other words, some developers are 10 times more productive than others. And just as the adoption of uniform approaches to training and conditioning has shrunk the variation in times between competitors in athletic competitions such as track and field, I think at least part of the difference in the productivity of software developers can be overcome by applying repeatable and proven practices to the software development process.&lt;br /&gt;&lt;br /&gt;Tools can help in this regard by integrating structured practices into the normal workflow of developers, for example, by including a unit testing framework.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Lack of Integration&lt;/strong&gt;&lt;br /&gt;The primary cause of the problem is that over time many organizations have accumulated a collection of software development lifecycle (SDLC) tools through purchase, acquisition or merger, or even custom development. Unfortunately, in most cases these tools weren’t designed to be used together and are not integrated with the IDEs in use in the organization. As a result, this lack of integration can manifest itself in myriad ways but often bubbles to the surface as follows:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;The data collected by the tools they use in their SDLC exist in separate silos and is not easily integrated or related to data from other tools.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;The tools they use don’t provide a platform and device independent way to implement extensibility and custom tools.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Using “best of breed” tools forces their team members to context-switch between tools in order to perform functions of their process.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;The tools they use don’t know about the policies or constraints of their process. In other words, their tools cannot interact in any meaningful way with the processes they do have.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;Obviously, the size of the overall integration problem is more often than not proportional to the size of the organization you’re in. However, even small organizations are not immune from integration issues as even a single relied upon tool that isn’t integrated can manifest all of the above issues.&lt;br /&gt;&lt;br /&gt;One approach to this problem, and that taken by VSTS as you’ll see in the next article, would be to integrate the lifecycle tools directly into the software that team members use in their day to day work. For example, rather than require a developer to go to a web site to too see which features he’s been assigned why not make those features visible from inside his IDE? And further, why not have the tool associate the feature with the actual source code and unit tests he’s working on so that metrics can be automatically collected on the implementation of the task.&lt;br /&gt;A second way in which lack of integration rears its ugly head is when tools don’t work together to surface or expose policies adopted by the organization. Typically these policies or guidelines that attempt to regulate the software development process exist only in three-ring binders or if you’re fortunate on an Intranet. Unfortunately, in both cases out of sight is out of mind and so the policies end up being enforced across the organization only sporadically if at all.&lt;br /&gt;&lt;br /&gt;What is needed is for tools to enforce policies dynamically during the regular work flow of team members. One of the bets Microsoft is making with VSTS is that once development tools automate process guidance, then most of the overhead associated with the process as well as the majority of the resistance to compliance will evaporate.&lt;br /&gt;&lt;br /&gt;It is this kind of deep integration, both in terms of your team member’s workflow and tools, can improve the productivity of you teams and the quality of the software you produce.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Lack of Support for the Process&lt;/strong&gt;&lt;br /&gt;Trying to coordinate the people, geographies, roles, and tools involved in projects while at the same time tracking and making predictions about the interaction of these aspects would be a challenge for anyone. So how do teams solve these sorts of problems and raise their level of success?&lt;br /&gt;&lt;br /&gt;The standard answer to that question has been to adopt a software development methodology such as the Rational Unified Process (RUP) or Extreme Programming (XP) or a customized version of one of these or other standard approaches. While this approach can be and often is effective, most developers don’t have access to tools that surface or provide visibility into the process so that they can more easily follow it. And because of the lack of tools support, the perceived complexity of some of these methodologies and simple inertia, some teams simply haven’t adopted any methodology or process at all. Unfortunately, these teams must instead fly by the seat of their pants much of the time. What is needed are tools that provide the overarching structure for projects in a way that teams can flexibly integrate their own process or use a predefined process that guides them on their way.&lt;br /&gt;&lt;br /&gt;Because many teams (primarily those in smaller organizations who don’t have the resources or expertise to implement a rigorous process) have not adopted a software development process there is ample opportunity for tools to provide guidance and therefore improve the quality and timeliness of software produced by these teams.&lt;br /&gt;&lt;br /&gt;Of course, the majority of larger organizations have already adopted a methodology and so their challenge is in making their process visible through the tools they use.&lt;br /&gt;&lt;br /&gt;What is needed is for tools to allow for the customization of boiler plate processes or the building of custom processes that integrate with the tools.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Summing it Up&lt;/strong&gt;&lt;br /&gt;In this article I’ve discussed a number of common problems teams face when developing solutions in the increasingly complex and constrained world of software development and hinted at how VSTS will address them.&lt;br /&gt;&lt;br /&gt;What is needed in order to solve these kinds of problems what is needed is not just another upgrade of their integrated development environment, but instead an “integrated services environment” that encompasses the entire extended software development team.&lt;br /&gt;&lt;br /&gt;At its core this integrated services environment, in order to be successful, needs to accomplish three things:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Reduce the complexity of delivering modern service-oriented solutions&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Be tightly integrated and facilitate better team collaboration and communication&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Enable customization and extensibility by organizations and ISVs &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;Exactly how VSTS is constructed to make this happen will have to wait for the next article.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113891073016793611?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113891073016793611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113891073016793611&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113891073016793611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113891073016793611'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/02/vsts-whys-and-hows.html' title='VSTS Whys and Hows'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113874766174363548</id><published>2006-01-31T14:28:00.000-08:00</published><updated>2006-01-31T14:47:41.756-08:00</updated><title type='text'>Using Local Transactions</title><content type='html'>In &lt;a href="http://realsoa.blogspot.com/2006/01/data-access-helpers.html"&gt;my last post&lt;/a&gt; I talked a bit about how the DataFactory class we're using is structured. In the past &lt;a href="http://realsoa.blogspot.com/2005/10/transaction-handling-in-edaf.html"&gt;I've written about&lt;/a&gt; how we implement transactional behavior &lt;em&gt;across&lt;/em&gt; business actions by utilizing the EDAF Context and Enterprise Services through the EDAF transaction handler.&lt;br /&gt;&lt;br /&gt;Of course &lt;em&gt;within&lt;/em&gt; a business action we also need to implement transactional behavior, for example, when an action makes calls to multiple stored procedures that need to be implemented in a single unit of work. To do this we could use simply configure the transaction handler in the pipeline for the business action. However, doing so incurs additional overhead because of the precense of the handler and the need to start a new MSDTC transaction.&lt;br /&gt;&lt;br /&gt;To implement a lighter weight approach we've added support for local transactions to our DataFactory. The DataFactory exposes a BeginTransaction method that opens a database connection and return an object that implements the IDbTransaction interface. The methods of the factory are then overloaded to accept the transaction object and therefore can use it across multiple calls.&lt;br /&gt;&lt;br /&gt;So the pattern for using local transactions is....&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;// get the data factory to use&lt;br /&gt;// (a property of our BusinessObjectBase class)&lt;br /&gt;DataFactory df = this.GetDataFactory(FactoryType.Write);&lt;br /&gt;&lt;br /&gt;IDbTransaction tx = null;&lt;br /&gt;IDbConnection connection=null;&lt;br /&gt;int ret = 0;&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;  // create a transaction to use&lt;br /&gt;  tx = df.BeginTransaction(IsolationLevel.ReadCommitted);&lt;br /&gt;  // grab the connection since the Rollback wipes out&lt;br /&gt;  // the property of the transaction object&lt;br /&gt;  connection = tx.Connection;&lt;br /&gt;              &lt;br /&gt;  HybridDictionary parms = new HybridDictionary();&lt;br /&gt;  parms.Add("partner_country_code",&lt;br /&gt;    req.CCQOrder.PartnerCountryCode);&lt;br /&gt;  // etc.&lt;br /&gt;&lt;br /&gt;  df.ExecuteNonQuery("InsertCCQNeed",parms,out ret,tx);&lt;br /&gt;&lt;br /&gt;  // call a second sproc&lt;br /&gt;  HybridDictionary ccqParms = new HybridDictionary();&lt;br /&gt;  ccqParms.Add("partner_country_code",&lt;br /&gt;    req.CCQOrder.PartnerCountryCode);&lt;br /&gt;&lt;br /&gt;  df.ExecuteNonQuery("InsertCCQ",ccqParms,out ret,tx);&lt;br /&gt;&lt;br /&gt;  // commit the transaction&lt;br /&gt;  tx.Commit();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;catch (System.Exception ex)&lt;br /&gt;{&lt;br /&gt;  if (tx != null)&lt;br /&gt;  {&lt;br /&gt;    if (tx.Connection.State == ConnectionState.Open)&lt;br /&gt;      tx.Rollback();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;finally&lt;br /&gt;{&lt;br /&gt;  if (connection != null)&lt;br /&gt;  {&lt;br /&gt;    // release to the pool&lt;br /&gt;    if (connection.State == ConnectionState.Open)&lt;br /&gt;      connection.Close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113874766174363548?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113874766174363548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113874766174363548&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113874766174363548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113874766174363548'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/01/using-local-transactions.html' title='Using Local Transactions'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113830887893000340</id><published>2006-01-26T12:39:00.000-08:00</published><updated>2006-01-26T14:22:03.336-08:00</updated><title type='text'>Data Access Helpers</title><content type='html'>Today I thought I'd drill into one of the core components we use in our service oriented infrastructure and invoked from inside our EDAF business actions and business components that implement our service operations. Like most applications, in order communicate with our enterprise database we use a data access helper component written in .NET v1.1 called the DataFactory. First though, a short digression on the nature of data access helpers.&lt;br /&gt;&lt;br /&gt;Architecturally, Data Access Helpers are Data Access Logic (DAL) Components that are internal to the Data Services Layer. As such, these components are called from the bodies of methods in the components that make up the public interface of the Data Services Layer. As a result, they are used via composition with other Data Access Logic components and primarily for the following reasons:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Code Simplification&lt;/strong&gt;. By abstracting code that is often duplicated in similar classes, developers can be more productive by having less code to write.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Provider Abstraction&lt;/strong&gt;. Since ADO.NET is built on the concept of .NET Data Providers, or specific concrete classes used to connect to either a narrow (like SQL Server or Oracle) or broad (like ODBC and OLE DB) data source, data access helpers can abstract the provider code thereby allowing the code to execute against different providers without recompilation.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Database Interface&lt;/strong&gt;. Data Access helpers can also incorporate code to dynamically discover and call database object such as stored procedures. In this way, data access helpers provide an interface to the database. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition to the MSDN Data Access Application Blocks, you can use a variety of home grown approaches, two of which I've discussed more fully in chapter 18 of &lt;em&gt;&lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0672323869/qid=1095187034/sr=1-3/ref=sr_1_3/104-7350429-9787116?v=glance&amp;s=books"&gt;Teach Yourself ADO.NET in 21 Days&lt;/a&gt;&lt;/em&gt;. In order to understand how our DataFactory works let's first review it's poor cousin the ProviderFactory.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Provider Factory&lt;/strong&gt;&lt;br /&gt;This class of approximately 120 lines is a variant of the &lt;em&gt;Abstract Factory Pattern&lt;/em&gt; documented by the GoF. This class abstracts the creation of .NET Data Provider specific objects into a single class that exposes factory methods for each of the four primary kinds of concrete classes in the provider.&lt;br /&gt;&lt;br /&gt;The parent object then simply needs to create an instance of the ProviderFactory and call the factory’s methods in place of the instantiation of concrete classes. For example: &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;IDbCommand com = _pf.CreateCommand(“usp_GetProduct”, con); &lt;/span&gt;&lt;/p&gt;&lt;p&gt;As a result, there is basically a one to one correspondence between the code with or without the ProviderFactory.&lt;br /&gt;&lt;br /&gt;Internally, the ProviderFactory relies on the Activator.CreateInstance method to create objects of the appropriate type and cast them to the generic interface supported in the System.Data namespace.&lt;br /&gt;&lt;br /&gt;For example, the code for the CreateCommand method is as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Public Function CreateCommand(ByVal cmdText As String,&lt;br /&gt;  _ ByVal connection As IDbConnection) As IDbCommand&lt;br /&gt;  Dim c As IDbCommand&lt;br /&gt;  c = CType(Activator.CreateInstance(_comType(_pType), _&lt;br /&gt;    False), IDbCommand)&lt;br /&gt;  c.CommandText = cmdText&lt;br /&gt;  c.Connection = connection&lt;br /&gt;  Return c&lt;br /&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You’ll notice that the CreateInstance method accepts the type of object to create stored in the array _comType. The array is defined as a private class level variable like so:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Private _comType(3) As Type&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And populated in the instance constructor as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;_comType(ProviderType.SqlClient) = GetType(SqlCommand)&lt;br /&gt;_comType(ProviderType.OLEDB) = GetType(OleDbCommand)&lt;br /&gt;_comType(ProviderType.ODBC) = GetType(OdbcCommand)&lt;br /&gt;_comType(ProviderType.Oracle) = GetType(OracleCommand)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The ProviderType enumeration is a custom enumeration that references the supported providers. In this case the four providers that ship with VS .NET 2003 are hardcoded into the constructor.&lt;br /&gt;&lt;br /&gt;Now let's move on to the DataFactory and discuss the three key features of the factory including:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Provider Abstraction&lt;/strong&gt;. Since the data factory needn’t expose provider specific objects for the most part, the technique used to abstract the provider is different from that used in the provider factory. Although it could also be rolled into the provider factory class. The data factory class is hard-coded to use any of the four providers that ship with VS .NET 2003 but can extended through a configuration file to include other providers.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Database Independence&lt;/strong&gt;. Independence from syntax particular to a database server is accomplished in the data factory through the use of XML statement files. These files include the database specific syntax (i.e. the actual Transact-SQL statements used against SQL Server) to define the commands that get executed. Statement files can be used both with stored procedures and inline SQL.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Caching&lt;/strong&gt;. Internally, the data factory caches instantiated command objects in a shared Hashtable that is checked each time a command is executed. In order to alleviate contention for the command object, its ICloneable interface is used to create copies of the object when it is needed. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The data factory class exposes the following members. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;*CacheFilePath&lt;/li&gt;&lt;li&gt;*Connection &lt;/li&gt;&lt;li&gt;*Provider &lt;/li&gt;&lt;li&gt;*UseCache &lt;/li&gt;&lt;li&gt;BeginTransaction &lt;/li&gt;&lt;li&gt;CreateDataAdapter &lt;/li&gt;&lt;li&gt;CreateSqlFiles (shared) &lt;/li&gt;&lt;li&gt;CreateSqlFile (shared) &lt;/li&gt;&lt;li&gt;ExecuteDataReader &lt;/li&gt;&lt;li&gt;ExecuteNonQuery &lt;/li&gt;&lt;li&gt;ExecuteScalar &lt;/li&gt;&lt;li&gt;ExecuteSqlXmlReader &lt;/li&gt;&lt;li&gt;GetDataSet &lt;/li&gt;&lt;li&gt;GetDataTable &lt;/li&gt;&lt;li&gt;GetProviders (shared) &lt;/li&gt;&lt;li&gt;GetXsltResults &lt;/li&gt;&lt;li&gt;RemoveStatement &lt;/li&gt;&lt;li&gt;SyncDataSet &lt;/li&gt;&lt;li&gt;SqlFilesCreated (event) &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The “Execute” methods execute statements and either don’t return results or return a reader that must be traversed. The “Get” methods return complete objects. &lt;/p&gt;&lt;p&gt;The class makes heavy use of overloading to supply varying signatures for many of the methods. For example, the ExecuteNonQuery method includes four overloaded signatures defined as follows:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;public int ExecuteNonQuery(string statement, HybridDictionary parms)&lt;br /&gt;&lt;br /&gt;public int ExecuteNonQuery(string statement, HybridDictionary parms,&lt;br /&gt;ref int returnVal)&lt;br /&gt;&lt;br /&gt;public int ExecuteNonQuery(string statement, HybridDictionary parms,&lt;br /&gt;ref int returnVal, IDbTransaction transaction)&lt;br /&gt;&lt;br /&gt;public int ExecuteNonQuery(string statement, HybridDictionary parms,&lt;br /&gt; ref int returnVal, IDbTransaction transaction,&lt;br /&gt; ref Object[] outputParms)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the statement name is passed into the methods as a string while the parameters to the statement are passed in a HybridDictionary object.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note:&lt;/em&gt; A System.Collections.Specialized.HybridDictionary object uses a ListDictionary for internal storage when the number of items in the collection is small and a Hashtable when the number of items is large. This is the case since the Hashtable is not as efficient for storing a small number of elements.&lt;br /&gt;&lt;br /&gt;The Provider property, which can be passed to the constructor or is defaulted to SqlClient, is used by the private _createProviderTypes method to create Type objects to hold the provider specific types. It does this either by using a hardcoded case statement or reading from a DataFactory.config file.&lt;br /&gt;&lt;br /&gt;Once the types are created it uses the CreateInstance method of the System.Activator class to instantiate the provider specific objects at the appropriate times as shown in the snippet from _createProviderTypes:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Private Sub _createProviderTypes()&lt;br /&gt; Select Case Me.Provider&lt;br /&gt;  Case "SqlClient"&lt;br /&gt;    _conType = GetType(SqlConnection)&lt;br /&gt;    _comType = GetType(SqlCommand)&lt;br /&gt;    _drType = GetType(SqlDataReader)&lt;br /&gt;    _daType = GetType(SqlDataAdapter)&lt;br /&gt;    _parmType = GetType(SqlParameter)&lt;br /&gt;  Case Else&lt;br /&gt;    ' Load the types from the configuration file&lt;br /&gt; End Select&lt;br /&gt;&lt;br /&gt; ' Create an instance of the connection object&lt;br /&gt; _connection = CType(Activator.CreateInstance(_conType, _&lt;br /&gt;   False), IDbConnection)&lt;br /&gt; _connection.ConnectionString = _connect&lt;br /&gt;End Sub&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In order to abstract the vendor specific SQL syntax from the data factory, each SQL command is encapsulated in an XML statement file like that here.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;DataFactory&amp;gt;&lt;br /&gt;  &amp;lt;Statement name="GetTitles" type="StoredProcedure"&amp;gt;&lt;br /&gt;    &amp;lt;Sql&amp;gt;usp_GetTitles&amp;lt;/Sql&amp;gt;&lt;br /&gt;    &amp;lt;Parameters&amp;gt;&lt;br /&gt;     &amp;lt;Param name="author" SqlName="@author" type="string“&lt;br /&gt;       maxLength="30" direction="Input" /&amp;gt;&lt;br /&gt;     &amp;lt;Param name="title" SqlName="@title" type="string“&lt;br /&gt;       maxLength="100" direction="Input" /&amp;gt;&lt;br /&gt;    &amp;lt;/Parameters&amp;gt;&lt;br /&gt;  &amp;lt;/Statement&amp;gt;&lt;br /&gt;&amp;lt;/DataFactory&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Note that the statement file includes a name attribute that contains the friendly name while the Sql element contains the SQL statement. Each parameter to the statement is defined in a Param element and optionally includes the length, direction, and the SourceColumn to map the parameter to in a DataTable.&lt;br /&gt;&lt;br /&gt;In this case a stored procedure is referenced but statement files can also be used to handle inline SQL. For example, the Sql element could be replaced with:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;sql&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;SELECT * FROM Titles WHERE author = @author AND title LIKE @title + ‘%’&lt;/span&gt;&lt;/sql&gt; &lt;/p&gt;&lt;p&gt;And the resulting statement file would be functionally equivalent to that shown on the slide.&lt;br /&gt;&lt;br /&gt;Internally, the data factory class uses shared, synchronized, provider-specific Hashtable objects (since there may be multiple instances of the data factory using different providers) to store statement objects that have been parsed into structures using an XmlTextReader. The structure definitions are (in VB):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Friend Structure Statement&lt;br /&gt;  Public Name As String&lt;br /&gt;  Public SQL As String&lt;br /&gt;  Public CommandType As CommandType&lt;br /&gt;  Public Parms As ArrayList&lt;br /&gt;  Public Command As IDbCommand&lt;br /&gt;End Structure&lt;br /&gt;&lt;br /&gt;Friend Structure Parm&lt;br /&gt;  Public Name As String&lt;br /&gt;  Public SQLName As String&lt;br /&gt;  Public Type As String&lt;br /&gt;  Public Direction As ParameterDirection&lt;br /&gt;  Public maxLength As Integer&lt;br /&gt;  Public SourceColumn As String&lt;br /&gt;End Structure&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The Hashtable object that holds each of the provider-specific Hashtable objects is declared as (in VB):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Private Shared _provCache As Hashtable =&lt;br /&gt;  Hashtable.Synchronized(New Hashtable())&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;After the statement files have been created and are read into an instance of the Statement structure they are placed in provider-specific Hashtable that is assigned to the instance when the Provider property is set.&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;When a statement is executed the private _getStatement method does the following:&lt;br /&gt;&lt;br /&gt;1. Determine if the statement is in the cache&lt;br /&gt;2. If not it loads and parses the statement file creating the command object with parameters before placing the command in the cache&lt;br /&gt;3. If so then it pulls the command object out of the cache and clones it&lt;br /&gt;4. It then populates the parameters&lt;br /&gt;5. And finally returns the command&lt;br /&gt;&lt;br /&gt;The most interesting code in this method is that used to find the statement if it exists and then to instantiate the command object accordingly. &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;' See if its in the cache&lt;br /&gt;If Not Me.UseCache OrElse _procs.ContainsKey(statement) Then&lt;br /&gt;  ' Pull it out of the cache&lt;br /&gt;  s = CType(_procs.Item(statement), statement)&lt;br /&gt;  newCom = CType(_cloneObject(s.Command), IDbCommand)&lt;br /&gt;Else&lt;br /&gt;  s = _getStatementFromFile(statement)&lt;br /&gt;  ' Build the command, add the parameters&lt;br /&gt;  com = CType(Activator.CreateInstance(_comType, False), _&lt;br /&gt;   IDbCommand)&lt;br /&gt;  com.CommandText = s.SQL&lt;br /&gt;  com.CommandType = s.CommandType&lt;br /&gt;  ' Add the parameters&lt;br /&gt;  ' Add the statement to the cache and clone it&lt;br /&gt;End If&lt;br /&gt;' Populate the parameters&lt;br /&gt;Return newCom&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The _cloneObject method relies on the ICloneable interface to create a copy of the command object whos parameters can be populated.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note:&lt;/em&gt; Only providers who command objects support deep copies using the ICloneable interface will work with the data factory.&lt;br /&gt;&lt;br /&gt;We've had good success with the DataFactory since it simplifies the code we need to write in our business actions, provides a level of abstraction when stored procedures change, and improves performance by caching command objects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113830887893000340?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113830887893000340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113830887893000340&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113830887893000340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113830887893000340'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2006/01/data-access-helpers.html' title='Data Access Helpers'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113468626073634556</id><published>2005-12-20T14:37:00.000-08:00</published><updated>2005-12-20T14:00:38.470-08:00</updated><title type='text'>Localizing Services</title><content type='html'>Since our service-oriented infrastructure is meant to be extended for use by partner countries we architected it so that different service consumer's culture settings could be taken into account. &lt;br /&gt;&lt;br /&gt;As discussed in my post on &lt;a href="http://realsoa.blogspot.com/2005/10/messaging-standards.html"&gt;Messaging Standards&lt;/a&gt; this meant incorporating into our standard SOAP header the Culture and UICulture elements defined as follows:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Culture &lt;/em&gt;(Optional) The culture setting for the client specifying the formats of date time, currency, and numeric data that follows RFC 1766 derived from ISO 639-1 and ISO 3166, e.g. US English="en-US"&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;UICulture &lt;/em&gt;(Optional) The culture setting for the client specifying the language to use that follows RFC 1766 derived from ISO 639-1 and ISO 3166, e.g. US English="en-US"&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;In order to set the culture and to return messages in the appropriate language we then had to effect several areas of our code. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ServiceAgentBase&lt;/strong&gt;&lt;br /&gt;From the service consumer's perspective a call to a service operation can be made through a Service Agent using our Service Agent Framework. The &lt;em&gt;layer supertype&lt;/em&gt; in that framework is our ServiceAgentBase class from which all service agents are defined.&lt;br /&gt;&lt;br /&gt;When a method on one of the derived service agent classes is called, the implementation delegates much of the work to a protected method of the ServiceAgentBase such as ExecuteOperation. This method is then responsible for building the SOAP request, choosing a transport, and then sending the request and receiving the response. &lt;br /&gt;&lt;br /&gt;In order to build the SOAP message the method uses a set of schema classes we generated using XSD.exe and then modified. For example, we have a class simply called Compassion.Schemas.Common.SoapHeader that encapsulates our header schema. In that class we have the following:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;public class SoapHeader&lt;br /&gt;{&lt;br /&gt;  private string _culture = &lt;br /&gt;   Thread.CurrentThread.CurrentCulture.Name;&lt;br /&gt;  private string _uiculture = &lt;br /&gt;   Thread.CurrentThread.CurrentUICulture.Name;&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;As a result, clients who instantiate service agents can first set the culture on the current thread (typically the culture is already set of course) before doing so and thereby transmit the culture through the SOAP envelope.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Thread.CurrentThread.CurrentCulture = &lt;br /&gt; new CultureInfo("de-DE");&lt;br /&gt;&lt;br /&gt;Thread.CurrentThread.CurrentUICulture = &lt;br /&gt; new CultureInfo("de-DE");&lt;br /&gt;&lt;br /&gt;// Create the update request&lt;br /&gt;ConstituentUpdateRequest req = CreateRequest();&lt;br /&gt;&lt;br /&gt;// Create the service agent&lt;br /&gt;ConstituentServiceAgent agent = new ConstituentServiceAgent&lt;br /&gt; ("Compassion.Services.Agent.Constituent.Tests.Unit");&lt;br /&gt;&lt;br /&gt;// Send the request and get the response&lt;br /&gt;ConstituentUpdateResponse resp = &lt;br /&gt; agent.UpdateConstituent(req);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;In this way, by using the service agent consumers will automatically get consideration for their culture when service operations are processed.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;WebService Transport&lt;/strong&gt;&lt;br /&gt;When the SOAP message reaches the server EDAF intercepts the request and processes through one of its transports. Thus far we've used the WebService transport exclusively and so we modified the standard code to be aware of our SOAP headers.&lt;br /&gt;&lt;br /&gt;Within the WebServiceInterfaceAdapter.cs file we added code to process our SOAP headers if the headers match our namespace. If so the code unpacks the header and then builds a CIHeader object which it then places in the EDAF Context object like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;// Create the header if it doesn't exist yet&lt;br /&gt;if (h == null) { h = new csc.CIHeader();}&lt;br /&gt;&lt;br /&gt;switch (sun.Element.LocalName) &lt;br /&gt;{&lt;br /&gt; case "Culture":&lt;br /&gt; {&lt;br /&gt;   h.Culture  = sun.Element.InnerText;&lt;br /&gt;   break;&lt;br /&gt; }&lt;br /&gt; case "UICulture":&lt;br /&gt; {&lt;br /&gt;   h.UICulture  = sun.Element.InnerText;&lt;br /&gt;   break;&lt;br /&gt; }&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;//Add the header to the context&lt;br /&gt;_context.Add("ciHeader",h,false);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;One of the interesting aspects of this is that if the WebServiceInterfaceAdapter does not find the culture settings in the SOAP header it will try and read them from the underlying transport itself, in this case HTTP like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;if (h.UICulture == null)&lt;br /&gt;{&lt;br /&gt;  // See if you can find the culture in the HTTP header&lt;br /&gt;  if (HttpContext.Current.Request.UserLanguages !=null) &lt;br /&gt;  {&lt;br /&gt;    if &lt;br /&gt;    (HttpContext.Current.Request.UserLanguages.Length &gt; 0)&lt;br /&gt;    {&lt;br /&gt;      // Take the first one in the collection&lt;br /&gt;      h.UICulture =&lt;br /&gt;       HttpContext.Current.Request.UserLanguages&lt;br /&gt;        [0].ToString();&lt;br /&gt;      if (h.Culture == null)&lt;br /&gt;      {&lt;br /&gt;        h.Culture =&lt;br /&gt;        HttpContext.Current.Request.UserLanguages&lt;br /&gt;         [0].ToString();&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;At this point the culture is now captured on the service provider side. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;BusinessActionBase&lt;/strong&gt;&lt;br /&gt;After the request passes through the adapter and any handlers that have been configured it makes it's way to the business action where the actual work is done. All of our business actions are derived from our BusinessActionBase class which as you might expect, contains the code to read the culture information and use the .NET ResourceManager to allow the derived class to pick up the correct strings.&lt;br /&gt;&lt;br /&gt;The supertype does this by simply examining the CIHeader object in the Context if it exists and then pulling the values out.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;//try to pull it from the ciHeader.&lt;br /&gt;if (Header != null)&lt;br /&gt;{&lt;br /&gt;  if ((Header.Culture != null) &amp;&amp; &lt;br /&gt;   (Header.Culture.Trim().Length&gt;0))&lt;br /&gt;    culture = Header.Culture;&lt;br /&gt;  if ((Header.UICulture != null) &amp;&amp; &lt;br /&gt;   (Header.UICulture.Trim().Length&gt;0))&lt;br /&gt;    uiCulture = Header.UICulture;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//try to pull it from the app settings.&lt;br /&gt;if (culture==string.Empty)&lt;br /&gt;  culture = ConfigurationSettings.AppSettings["Culture"];&lt;br /&gt;if (uiCulture==string.Empty)&lt;br /&gt;  uiCulture = ConfigurationSettings.AppSettings&lt;br /&gt;   ["UICulture"];&lt;br /&gt;&lt;br /&gt;//call SetCulture&lt;br /&gt;SetCulture("Strings",&lt;br /&gt; this.GetType().Assembly,strCulture,strUICulture);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;You'll also notice that this code includes a last ditch effort to pull the culture settings from the application's configuration file. This allows the implementer of the service to set a default culture other than the neutral culture.&lt;br /&gt;&lt;br /&gt;The last line of code above calls the SetCulture method in order to actually set the culture. The key part of the SetCulture method sets the current thread's culture to the codes passed in and instantiates the ResourceManager that is then exposed via a protected property. &lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Thread.CurrentThread.CurrentCulture = new &lt;br /&gt;  CultureInfo(strCultureCode);&lt;br /&gt;&lt;br /&gt;Thread.CurrentThread.CurrentUICulture = new&lt;br /&gt;  CultureInfo(strUICultureCode);&lt;br /&gt;&lt;br /&gt;m_objResourceManager = new ResourceManager&lt;br /&gt; (strResourceFileBaseName,objCaller);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The end result is that dervied business actions use the exposed resource manager to return exception and other messages to the client in their own language. For example, when an exception is raised the business action would code like the following in order to return an exception code and message to the caller.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;exception.Message = &lt;br /&gt; this.ResourceManager.GetString("MissingAddress");&lt;br /&gt;exception.Code=&lt;br /&gt; this.ResourceManager.GetString("MissingAddressCode");&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113468626073634556?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113468626073634556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113468626073634556&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468626073634556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468626073634556'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/12/localizing-services.html' title='Localizing Services'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113468638169474800</id><published>2005-12-20T07:39:00.000-08:00</published><updated>2005-12-20T07:26:07.693-08:00</updated><title type='text'>Business Rules in the SOI</title><content type='html'>One of the architectural topics that caused our team more than a bit of thinking was our approach to implementing rules.&lt;br /&gt;&lt;br /&gt;The original idea for handling rules as noted in the high-level architecture diagram below (to the left of the Business Action) was to implement a common rules engine that would be responsible for the storage and execution of rules. This approach would allow for one-stop shopping for &lt;a href="http://realsoa.blogspot.com/2005/05/implementing-services.html"&gt;Process and Entity Services&lt;/a&gt; as well as a common repository for easily changing rules.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/arch.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2568/246/320/arch.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Initially three different options were discussed:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?EventID=1032273113&amp;EventCategory=5&amp;amp;culture=en-US&amp;CountryCode=US"&gt;&lt;strong&gt;BizTalk Rules Engine (BRE)&lt;/strong&gt;&lt;/a&gt;. Since BizTalk is a major player in the Compassion SOA and includes a rules engine, our first thought was to leverage this engine to store and execute rules. &lt;br /&gt;&lt;br /&gt;While the engine is versatile and can be called from inside .NET assemblies (such as the business actions we’ll be developing), the major impediment to using the engine was twofold: 1) The BRE does not include an easy to use interface for managing the rules. As a result, other organizations have created their own interfaces using tools like Microsoft Excel to manage the rules. Without doing something like this rules could not be managed by business user, 2) when using the BRE a BizTalk installation is required with the appropriate licensing. This model may not be desirable if services are deployed in a partner country since it would force the adoption of BizTalk at those locations. &lt;br /&gt;&lt;br /&gt;From a previous concall with Microsoft it is also not anticipated that Microsoft will ship the BRE as a separate product in the near future.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;NxBRE&lt;/strong&gt;. A second approach that was considered was adopting the open-source rules engine for the .NET Platform called NxBRE, which is a port of the JxBRE engine available at SourceForge. This engine use rules defined in RuleML and allows for rules to be defined using Visio stencils. One of our consultants performed an evaluation of NxBRE to determine how it could be invoked from within business actions. &lt;br /&gt;&lt;br /&gt;After evaluating this option it was decided that although it overcomes the licensing restrictions implicit in the use of the BizTalk BRE it still does not provide a simple way for business users to easily change the rules. Further, as with the BizTalk BRE, NxBRE is an inference engine that works off the concepts of Facts, Queries, and Implications. This structure would work well for simple data validation but would be unwieldy when trying to represent data modification rules since a large number of facts would have to be loaded into the engine and the return data from the engine would be complex (for example to represent rules regarding how an entity’s attributes are set based on all of the data associated with the entity).&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Ultimus 7.1&lt;/strong&gt;. Version 7.1 of the BPM suite includes a rules engine called Ultimus Director that can be used from within Ultmus workflows to represent rules. It is designed with end users in mind and so can be used by business users to change and update rules without developer intervention. However, the engine is not meant to be invoked from outside Ultimus and it is assumed that licensing restrictions would apply. As a result, this option does not appear to be a general solution. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;In order to clarify Compassion’s position regarding the implementation of business rules in the SOA architecture a conference call with Gartner analyst Jim Sinur was held. He provided the following clarifications and best practices.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;1. The need for and use of BREs should be determined based on business rule volatility&lt;/p&gt;&lt;ul&gt;&lt;li&gt;That tipping point is usually in the range of 25-35% of the rules to be processed&lt;/li&gt;&lt;li&gt;Compassion should rank business rules by; change frequently, hardly ever change, and middle-of-the-road, that is, perform a volatility analysis&lt;/li&gt;&lt;li&gt;BREs may be cost effective for managing the rules that change frequently &lt;/li&gt;&lt;li&gt;Compassion may have few business rules that change frequently and a BRE would be overkill &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;2. BREs are expensive and there are currently no solid candidates in a .NET architecture&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Virgin Atlantic has created a custom spreadsheet interface to BizTalk for volatile business rules, this allows business analysts to change these rules without developer assistance &lt;/li&gt;&lt;li&gt;Microsoft may add a similar interface to BizTalk, however, this is just something Compassion should watch and not count on &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;3. Create guidelines for business rule placement &lt;/p&gt;&lt;ul&gt;&lt;li&gt;"Flow-Related" business rules should be placed in BizTalk or Ultimus &lt;/li&gt;&lt;li&gt;Business rules should be parameterized whenever possible - especially the more volatile rules &lt;/li&gt;&lt;li&gt;Avoid placing business rules within custom business framework services - especially any "flow-related" rules&lt;/li&gt;&lt;li&gt;Create and use a mechanism for business rule management &lt;/li&gt;&lt;li&gt;Report on what's there &lt;/li&gt;&lt;li&gt;Keep pulse of how often the rules are changed &lt;/li&gt;&lt;li&gt;Change the strategy if you discover a high degree of change&lt;/li&gt;&lt;li&gt;Create rules so they can be tailored to meet global requirements&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Approach&lt;/strong&gt;&lt;br /&gt;As a result of this analysis and the Gartner discussion the decision was made not to pursue adopting a BRE as a single repository for all rules within our service-oriented infratructure. The decision was based primarily on two factors. First, although a volatility analysis has not been done it is highly unlikely that Compassion meets the 25-35% threshold where implementing a BRE would be cost effective. Secondly, within our technology scope there doesn’t appear to be a BRE that could be employed without creating a custom UI and/or incurring licensing costs. As a result, the direction we’re following is to employ the native rules engines within BizTalk and Ultimus (Process Services) and then implement custom rule development within Entity and Infrastructure Services.&lt;br /&gt;&lt;br /&gt;In following this approach the following rules matrix was developed in order to provide guidance as to how and where rules would be implemented.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Process Rules&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;What?&lt;/em&gt;&lt;br /&gt;Rules related to the flow of a system to system process or system to human process, for example, a rule that changes the routing of a form within Ultimus based on partner country&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Where?&lt;/em&gt;&lt;br /&gt;Implemented in the BizTalk BRE or Ultimus Director when available&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Data Integrity Rules&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;What?&lt;/em&gt;&lt;br /&gt;Rules related to how data is ultimately stored in a data store such as Compass or an XML document including FK relationships and link tables, for example, a rule that dictates that when an email is updated the shared email addresses are also updated&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Where?&lt;/em&gt;&lt;br /&gt;Typically implemented in stored procedures that persist the data and invoked from business actions. If the data is persisted in XML documents, then XSDs can be used to implement these rules&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Data Modification Rules &lt;/strong&gt;&lt;br /&gt;&lt;em&gt;What?&lt;/em&gt;&lt;br /&gt;Rules related to how data can be inserted, updated, or deleted. Typically, these rules are dependant on the state of the persisted data in a data store, for example, a rules that specifies that in the US only two email addresses are stored&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Where?&lt;/em&gt;&lt;br /&gt;Implemented directly in business actions that perform inserts, updates, or deletes. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Data Validation Rules&lt;/strong&gt;&lt;em&gt;What?&lt;/em&gt;&lt;br /&gt;Rules related to the format of data, for example, the requirement that an email address conform to a regular expression &lt;br /&gt;&lt;br /&gt;&lt;em&gt;Where?&lt;/em&gt;&lt;br /&gt;Implemented directly in business actions that perform validation typically prior to inserts or updates&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In following with the best practices outlined by Gartner the Data Modification and Data Validation rules include support for externalization. Specifically, this support includes:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;The ability for a business action to be notified as to which rules to process based on a configurable value (such as the partner country) and on which client is invoking the service&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;The ability for the business action to use specific parameters for a rule based on a configurable value (such as the partner country)&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;We implemented this support using a custom EDAF handler as shown in the following diagram.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/rules.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2568/246/320/rules.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As indicated in the diagram the rules handler is invoked as a part of the service implementation pipeline for specific business actions. The handler passes configuration information indicating the local value along with the service action name to the rules store. The rules store returns two data structures, one that is a collection of rule identifiers (GUIDs) that should be processed for the business action, and a second that includes a collection of country specific values to use when processing the rules. Both data structures are placed into the EDAF Context. The Rules Handler caches the data structures once retrieved for performance reasons.&lt;br /&gt;&lt;br /&gt;The business action then uses the data structures in the Context to determine which rules to process and what values to use when processing. The semantics of the rules themselves are encoded in C# or VB .NET code, typically in private helper methods that make them easy to maintain. The collection of rule ids are used only to indicate which rules to process and so the presence of the id in the context triggers the execution of the rule. &lt;br /&gt;&lt;br /&gt;Because the two collections are not related, multiple rules can use the same local value in its processing.&lt;br /&gt;&lt;br /&gt;When rules are retrieved the handler queries against these two tables. Given the LocalValue, ServiceActionName and the client making the request (From information encapsulated in the SOAP header), a set of Active RuleIDs would be returned. If the the client doesn’t appear in the BusinessActionClientRules table, the Active flag from the BusinessActionRules table applies. Notice that the syntax of the rule is not included in the table, only the id and whether it is active for the business action and client. This data would then be placed in a hashtable within the EDAF Context object by the Rules Handler.&lt;br /&gt;&lt;br /&gt;Inside a business action, particularly the BusinessActionBase class, we've written code to check the hashtable for the RuleID before executing the rule.&lt;br /&gt;&lt;br /&gt;We've also built an ASP.NET user interface to manage the rule data.&lt;br /&gt;&lt;br /&gt;Overall, this solution has workd quite nicely and in production we use these rules both to provide specific values to use when evaluating a rule and to turn rules on and off for specific clients.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113468638169474800?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113468638169474800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113468638169474800&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468638169474800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468638169474800'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/12/business-rules-in-soi.html' title='Business Rules in the SOI'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113468664187657485</id><published>2005-12-15T14:43:00.000-08:00</published><updated>2005-12-16T14:34:09.956-08:00</updated><title type='text'>Using NLB</title><content type='html'>One of the design requirements for our service-oriented infrastructure was to support a scale out architecture. For our needs we chose to use Microsoft's Network Load Balancing (NLB) system.&lt;br /&gt;&lt;br /&gt;Early on we created a reference architecture in order to test the integration between our various components including EDAF services, BizTalk 2004, legacy ASP code, and Ultimus BPM 7.1. In our test environment we set up two clusters, one for the EDAF services and one for the Ultimus services.&lt;br /&gt;&lt;br /&gt;In the reference architecture simple tests of both the EDAF services cluster and the Ultimus cluster were performed. In the case of the former 200 requests were sent through one of our orchestrations which ended up invoking our constituent service via the service agent framework we devleoped. In the case of the latter 50 requests that created Ultimus incidents through our facade service at a time were spawned by a test harness. In both cases the tests (using performance monitor) revealed that all requests from a particular client were being serviced by one machine in the cluster. The machines servicing those requests were the servers that had the higher priority set in the NLB configuration in the Host Parameters tab.&lt;br /&gt;&lt;br /&gt;NLB settings were then reconfigured from single to "no affinity" and balancing load at 50% in the port rules from within the NLB UI. Tests were then re-executed with no difference in the results.&lt;br /&gt;&lt;br /&gt;Details regarding &lt;a href="http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/clustering/nlbfaq.mspx"&gt;the Microsoft NLB algorithm&lt;/a&gt; were consulted. The important paragraph of this document is:&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;&lt;span style="color:#ffff00;"&gt;"When inspecting an arriving packet, all hosts simultaneously perform a mapping to quickly determine which host should handle the packet. The mapping uses a randomization function that calculates a host priority based on their IP address, port, and other information. The corresponding host forwards the packet up the network stack to TCP/IP, and the other cluster hosts discard it. The mapping remains unchanged unless the membership of cluster hosts changes, ensuring that a given clients IP address and port will always map to the same cluster host. However, the particular cluster host to which the clients IP address and port map cannot be predetermined since the randomization function takes into account the current and past clusters membership to minimize remappings."&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;In other words, when “no affinity” is set, the host that services an incoming request is determined by the IP address and client port number in a deterministic fashion based on a randomization algorithm and the number of servers in the cluster.&lt;br /&gt;&lt;br /&gt;As a result we looked into how client port numbers are generated on client machines.&lt;br /&gt;&lt;br /&gt;It turned out that within our Service Agent framework we have a ServiceAgentBase class from which all servicce agents are derived. Within this class requests are executed using the SoapHttpWebClient class. Internal to this class the following code is in the constructor.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public SoapHttpWebClient(string requestUri)&lt;br /&gt;{&lt;br /&gt;_requestUri = requestUri;&lt;br /&gt;_httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(requestUri);&lt;br /&gt;_httpWebRequest.KeepAlive = false;&lt;br /&gt;_httpWebRequest.Method = "POST";&lt;br /&gt;_httpWebRequest.ContentType = "text/xml;charset=\"utf-8\"";&lt;br /&gt;_httpWebRequest.Accept = "text/xml";&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Tests using a throw away application and a network monitor utility revealed that requests were load balanced when the System.Net.Sockets.TcpClient was used to generate the requests but not when HttpWebRequest was used as in the constructor code above. This was the case since using TcpClient generates a new connection and therefore a unique port number for each request.&lt;br /&gt;&lt;br /&gt;However, by adding the following line of code to the constructor above…&lt;br /&gt;&lt;code&gt;&lt;br /&gt;_httpWebRequest.KeepAlive = false;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;the HttpWebRequest class creates a new connection for each request which allows the TCP stack on the machine to assign a unique port number to the request. Making this change to the SoapHttpWebClient entails a slight performance penalty on the client machine since connections cannot be reused. As a result, we added a configuration setting, &amp;lt;KeepAlives&amp;gt; to the configuration section for the service agent so that clients have the option of using this setting (with the default set to false).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113468664187657485?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113468664187657485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113468664187657485&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468664187657485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468664187657485'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/12/using-nlb.html' title='Using NLB'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113468578909752421</id><published>2005-12-15T14:17:00.000-08:00</published><updated>2005-12-15T14:29:49.116-08:00</updated><title type='text'>Inter Action Communication</title><content type='html'>One of the interesting issues we tackled in this release was that of allowing EDAF business actions to communicate their state information. &lt;br /&gt;&lt;br /&gt;Our original design made the assumption that we would have controller type business actions that would invoke other business actions using the in-process dispatching adapter in EDAF. Each of the invoked business actions would when necessary create exceptions and return those to the controller who would then add them to its exception collection that eventually is sent back to the caller as a series of XML elements. &lt;br /&gt;&lt;br /&gt;While this design allows the business actions to be independent and the controller to rollback the work of all the invoked actions, it does not allow for business actions that have dependencies to communicate when called by the controller. In other words the communication model here is essentially from the controller to each invoked action whereas pairs of invoked actions have no visibility to each other.&lt;br /&gt;&lt;br /&gt;Fortunately, EDAF allow for this by supporting the concept of a Context object. So the mechanism to do this is to add items to the EDAF Context object (this.Context) before invoking the action. We were using this technique already to send flags like a ValidateOnly flag that instructs each action to validate the request but do not process it. &lt;br /&gt;&lt;br /&gt;However, for this release we added the capability for actions to be aware of the exceptions that have been created within the entire request. We use a base class called BusinessActionBase from which all of our actions are derived. To this class we added a protected method called DoesExceptionExist that accepts one of our custom exception codes and looks in the context item with a specific key. If the item doesn’t exist it returns false.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;if (this.DoesExceptionExist("COUNTRY_CODE_NOT_FOUND")==false)&lt;br /&gt;{ …&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;When invoking an action that has dependencies developers can therefore add an ArrayList populated with exceptions (also provided by the base class) to the context before submitting the request. &lt;br /&gt;&lt;br /&gt;We added this capability because one of our actions needed to determine whether the COUNTRY_CODE_NOT_FOUND exception was previously thrown. So when action A invokes action B it does the following:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;// Added to context so exceptions can be searched&lt;br /&gt;daContext.Add("Exceptions",this.Exceptions);&lt;br /&gt;da.Submit(daContext);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;EDAF and our base class handle the rest.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113468578909752421?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113468578909752421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113468578909752421&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468578909752421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468578909752421'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/12/inter-action-communication.html' title='Inter Action Communication'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113468489300801525</id><published>2005-12-15T12:53:00.000-08:00</published><updated>2005-12-15T14:14:53.033-08:00</updated><title type='text'>Sweet!</title><content type='html'>Today we deployed the second release of our SOA project code-named "Sweet". We have four deliverables remaining and each is named after a type of pickle and include "Dill", "Half-Sour", "Kosher", and "Blue." It's a long story that came out of the requirements gathering process and too much caffeine at an offsite meeting.&lt;br /&gt;&lt;br /&gt;This release introduced a new EDAF based service built on the .NET Framework v1.1 to handle payment information and an augmentation of our service that manages constituents. We also introduced a new Ultimus 7.1 workflow to handle reconciling constituents and one updated and four new BizTalk 2004 orchestrations. Overall we deployed code to five application (two web servers, BizTalk, Ultimus, and our EDAF services machines) and four SQL Server database servers.&lt;br /&gt;&lt;br /&gt;From a schedule standpoint the work was done primarily by three in house developers and three consultants over a span of a little over two months and with the assistance of a QA manager. In that time the team modified or wrote 49 assemblies, 26 stored procedures, four ASP.NET and one ASP site, and one Ultimus workflow - some very nice work contributed across the board.&lt;br /&gt;&lt;br /&gt;Probably the biggest deployment challenge in this release involved introducing new BizTalk orchestrations while needing to keep existing production instances running. We had one core orchestration in our first release which was processing each request (which take on average 48 hours to complete with human interaction in Ultimus). In the Sweet release that orchestration became merely a component of a larger process as we incorporated the processing of new transaction types. So we had to create a new version of that orchestration that returned a response document among other things. &lt;br /&gt;&lt;br /&gt;So when we deployed we had over 100 orchestrations we suspended before deploying the new assemblies. Once we deployed we had to add a binding policy in the GAC to one of our schema assemblies that had changed and then we were able to resume the existing orchestrations (as an aside I had originally thought that deploying a new schema assembly would be problematic based on other things I had read but it turned out to be quite painless). As users in Ultimus completed their work and notified BizTalk via an HTTP receive, the orchestrations completed under the old version. New requests that were received via our EDAF service facade were then processed in the new version of the orchestration. Eventually, we'll be able to shut down the first version of the orchestration once all the existing Ultimus incidents have been resolved.&lt;br /&gt;&lt;br /&gt;We also learned that with the addition of new orchestrations and a new service we need to automate the installation of all components using msi packages. We used BizTalk scripts which worked well but ensuring that the GAC was updated correctly on our services machines along with configuration files made the deployment to five application and four database servers a two and half hour process that included a couple missed configuration settings.&lt;br /&gt;&lt;br /&gt;Architecturally the biggest challenge was in putting in place an "uber" orchestration that acts as the controller for all requests that are processed through our infrastructure to go along with a tracking database. This design will allow us to plug in new transaction types as we automate subsequent business processes. &lt;br /&gt;&lt;br /&gt;Other interesting aspects included building a web services operation that attempts to match sponsors to unvalidated information submitted to the process (a so called "Professed" request as opposed to a "Validated" one where the user has provided credentials) and called from an orchestration responsible for "reconciling" sponsor data, and (through some slick .NET coding) allowing the Ultimus user interface to act as a consumer of our services using our Service Agent framework in order to retrieve and create sponsors.&lt;br /&gt;&lt;br /&gt;Overall since our first release in September the service-oriented infrastructure has handled over 400,000 service requests and has been remarkably stable. I've been impressed with the EDAF infrastructure on which the services are based and BizTalk has easily handled the load we've thrown at it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113468489300801525?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113468489300801525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113468489300801525&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468489300801525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113468489300801525'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/12/sweet.html' title='Sweet!'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-113268718600303643</id><published>2005-11-22T11:14:00.000-08:00</published><updated>2005-11-22T11:19:46.013-08:00</updated><title type='text'>TDD and Visual Studio Team System</title><content type='html'>A co-worker brought &lt;a href="http://codebetter.com/blogs/scott.bellware/archive/2005/11/21/134910.aspx"&gt;this post&lt;/a&gt; by Scott Bellware to my attention on &lt;a href="http://msdn2.microsoft.com/en-us/library/ms182521.aspx\"&gt;the guidelines&lt;/a&gt; Microsoft has on MSDN for test-driven development and how these don't really conform to traditional TDD approaches.&lt;br /&gt;&lt;br /&gt;Scott makes some excellent points the most important of which IMHO are:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;TDD helps you design the code by writing the test first and then making the code conform through refactoring of the interfaces etc.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;TDD tests don’t necessarily map one to one with methods in a class&lt;/li&gt; &lt;br /&gt;&lt;br /&gt;This point about test generation in the tool came up at a developer event on Team System I attended last July in Redmond. I got the impression that the MSFT folks fully understood the concerns of the agile community (they were loudly voiced in much the same way Scott articulated in the blog) but that since not everyone was or is doing agile, having the autogeneration feature was still valuable. I agree that the guidelines miss the mark but that said there is a disclaimer in the document that they’re not following "traditional TDD". &lt;br /&gt;&lt;br /&gt;I could see an organization using a mix of both approaches based on the type of development you're doing. When designing a class library from scratch for use by other developers I might following the "traditional" route so that I'm not constrained in my design by my first thoughts, but when another developer uses my library and inherits from it they might like to autogenerate some unit tests. They are more constrained and so using the autogeneration might be more productive for them. &lt;br /&gt;&lt;br /&gt;We have this situation with the Service Agent Framework we built. I haven't spent that much time in VS2005 to know how I would use the Class Designer in the former approach but my guess is that as I refactor to conform the design to the test I’ll do most of that work in the Class Designer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-113268718600303643?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/113268718600303643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=113268718600303643&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113268718600303643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/113268718600303643'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/11/tdd-and-visual-studio-team-system.html' title='TDD and Visual Studio Team System'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-112860417800863006</id><published>2005-10-07T06:09:00.000-07:00</published><updated>2005-12-15T14:33:19.433-08:00</updated><title type='text'>Messaging Standards</title><content type='html'>Another aspect of the &lt;a href="http://realsoa.blogspot.com/2005/05/service-communication.html"&gt;Service Communication&lt;/a&gt; part of our services platform are the messaging standards. These include both the envelope standards used for encapsulating messages as well as the message headers we use.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Envelope Standard&lt;/strong&gt;&lt;br /&gt;This envelope standard defines the XML schema used to represent messages. Rather than create a new standard the CI-SOA will use the Simple Object Access Protocol (SOAP) 1.1 standard envelope defined at &lt;a href="http://www.w3.org/TR/2000/NOTE-soap-20000508/"&gt;http://www.w3.org/TR/2000/NOTE-soap-20000508/&lt;/a&gt;. As an example a request message looks as follows:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;soap:Envelope&lt;br /&gt; xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&lt;br /&gt; soap:encodingStyle=&lt;br /&gt;   "http://schemas.xmlsoap.org/soap/encoding/"/&amp;gt;&lt;br /&gt;   &amp;lt;soap:Header&amp;gt;&lt;br /&gt;       &amp;lt;t:Transaction&amp;gt;5&amp;lt;/t:Transaction&amp;gt;&lt;br /&gt;   &amp;lt;/soap:Header&amp;gt;&lt;br /&gt;   &amp;lt;soap:Body&amp;gt;&lt;br /&gt;       &amp;lt;m:GetLastTradePrice xmlns:m="Some-URI"&amp;gt;&lt;br /&gt;           &amp;lt;symbol&amp;gt;DEF&amp;lt;/symbol&amp;gt;&lt;br /&gt;       &amp;lt;/m:GetLastTradePrice&amp;gt;&lt;br /&gt;   &amp;lt;/soap:Body&amp;gt;&lt;br /&gt;&amp;lt;/soap:Envelope&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;This standard is intended to be used each time a service provider exchanges a message with a service consumer regardless of the binding used to call the service. For example, the same envelope will be used when invoking services over HTTP or MSMQ. As a result, our service agent framework builds SOAP v1.1 envelopes when services are invoked.&lt;br /&gt;&lt;br /&gt;Further, developers use document style encoding (as opposed to RPC-style encoding) with XML Schema (XSD) when possible since doing so makes it possible to support arbitrarily complex types in XML messages. The .NET Framework supports document style encoding by default.&lt;br /&gt;&lt;br /&gt;The reason the SOAP 1.1 standard is being used rather than SOAP 1.2 is that SOAP 1.1 is supported natively in the .NET Framework v1.1. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Header Standard&lt;/strong&gt;&lt;br /&gt;This header standard defines the XML schema used to add informational content to the Header element of the envelope. This information is useful for service management, routing, and security. &lt;br /&gt;&lt;br /&gt;The standard includes two parts. The first is the WS-Addressing schema found at &lt;a hfref="http://schemas.xmlsoap.org/ws/2004/08/addressing/"&gt;http://schemas.xmlsoap.org/ws/2004/08/addressing/&lt;/a&gt;. Elements in this schema are used for the following purposes.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Element Usage&lt;/strong&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;MessageID&lt;/em&gt; (Required)- A GUID that uniquely identifies this message. Useful for logging and duplicate message handling&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;To &lt;/em&gt;(Required) The physical address the message is being sent to. Useful for routing. A URL for HTTP requests or a direct format name for a queue in the form of a URN, e.g. urn:DIRECT=OS:compassion.com\PUBLIC\MyQueue;JOURNAL&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;From &lt;/em&gt;(Required) The service or application that created the message. Typically uses only the Address element formatted as a URN to identify the creator of the message. Useful for logging.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Action &lt;/em&gt;(Required) The soapAction for the operation being invoked &lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;ReplyTo &lt;/em&gt;(Optional) Contains an address used to send a response to. This can take the form of a URL for HTTP or a direct format queue name in the form of a URN. Optionally, this element may include reference properties if additional information is required for a particular endpoint. If not specified the reply is sent to the URI from which the original was sent. Services may also use this element in order to send delayed responses to a particular location. For example, the immediate response to the message may include an acknowledgement while the eventual complete response is sent to the ReplyTo address&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;RelatesTo &lt;/em&gt;(Optional) Populated in a response message from the request-response message exchange. Contains the MessageID of the original request message&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;The second schema is the http://schemas.compassion.com/common/headers/2005-04-05  schema that defines elements used within the SOAP Header element as well as the From element of WS-Addressing. The definition of the headers schema is as follows:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;xs:schema id="CIHeaders" &lt;br /&gt;targetNamespace=&lt;br /&gt; "http://schemas.compassion.org/common/headers/2005-04-05"&lt;br /&gt; elementFormDefault="qualified"&lt;br /&gt; xmlns:ch=&lt;br /&gt; "http://schemas.compassion.com/common/headers/2005-04-05"&lt;br /&gt; xmlns:xs="http://www.w3.org/2001/XMLSchema"&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="MesssageStreamID" type="xs:anyURI"&amp;gt; &lt;br /&gt;      &amp;lt;/xs:element&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="CreatorIdentity" &lt;br /&gt;   type="xs:string"&amp;gt;&amp;lt;/xs:element&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="DateTimeStamp" &lt;br /&gt;   type="xs:dateTime"&amp;gt;&amp;lt;/xs:element&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="ProcessID" &lt;br /&gt;   type="xs:anyURI"&amp;gt;&amp;lt;/xs:element&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="Culture" &lt;br /&gt;   type="xs:string"&amp;gt;&amp;lt;/xs:element&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The usage of the elements is as follows:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Element Usage&lt;/strong&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;MesssageStreamID &lt;/em&gt;(Required) A GUID that identifier a unique sequence of messages that flow through the SOA. Used for correlating messages and for logging purposes. If the creator of the message does not have a MessageStreamID in hand from a previous message, it should create one and place it in the Header.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;CreatorIdentity &lt;/em&gt;(Required) The windows account representing the creator of the message. Useful for logging and to authorize requests using the trusted subsystem model&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;DateTimeStamp &lt;/em&gt;(Required) Identifies in Coordinated Universal Time (UTC) when the message was created by the service consumer or provider. Useful for logging&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;ProcessID &lt;/em&gt;(Optional) A GUID that identifies a process. Typically populated by process services. If a service receives a ProcessID it should include it in subsequent messages&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Culture &lt;/em&gt;(Optional) The culture setting for the client specifying the formats of date time, currency, and numeric data that follows RFC 1766 derived from ISO 639-1 and ISO 3166, e.g. US English="en-US"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;UICulture &lt;/em&gt;(Optional) The culture setting for the client specifying the language to use that follows RFC 1766 derived from ISO 639-1 and ISO 3166, e.g. US English="en-US"&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;In the future we'll likely also add a PartnerCountryCode element that identifies the Compassion partner country from which the request originated. This will allow services to take different actions (for example processing different business rules) when the requests come from different countries.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br /&gt;The following is an example request message that employs the standards discussed in this document:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;soap:Envelope &lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   &lt;br /&gt; xmlns:xsd="http://www.w3.org/2001/XMLSchema"  &lt;br /&gt; xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" &lt;br /&gt; xmlns:ch=&lt;br /&gt;"http://schemas.compassion.com/common/headers/2005-04-05" &lt;br /&gt; xmlns:wsa=&lt;br /&gt;"http://schemas.xmlsoap.org/ws/2004/08/addressing"&amp;gt;    &lt;br /&gt;  &amp;lt;soap:Header&amp;gt;&lt;br /&gt;   &amp;lt;ch:MessageStreamID&amp;gt;uuid:bbbb-cccc-dddd-eeee&lt;br /&gt;   &amp;lt;/ch:MessageStreamID&amp;gt; &lt;br /&gt;   &amp;lt;ch:DateTimeStamp&amp;gt;2005-04-05:T18:00:00&lt;br /&gt;   &amp;lt;/ch:DateTimeStamp&amp;gt; &lt;br /&gt;   &amp;lt;ch:CreatorIdentity&amp;gt;ci/dfox&amp;lt;/ch:CreatorIdentity&amp;gt; &lt;br /&gt;   &amp;lt;ch:Culture&amp;gt;en-US&amp;lt;/ch:Culture&amp;gt; &lt;br /&gt;   &amp;lt;ch:UICulture&amp;gt;en-US&amp;lt;/ch:UICulture&amp;gt;&lt;br /&gt;   &amp;lt;wsa:MessageID&amp;gt;uuid:aaaa-cccc-dddd-eeee&lt;br /&gt;   &amp;lt;/wsa:MessageID&amp;gt; &lt;br /&gt;   &amp;lt;wsa:To&amp;gt;http://compassion.com/DemoService.asmx&lt;br /&gt;   &amp;lt;/wsa:To&amp;gt;&lt;br /&gt;   &amp;lt;wsa:Action&amp;gt;http://compassion.com/DemoServiceURI&lt;br /&gt;   &amp;lt;/wsa:Action&amp;gt; &lt;br /&gt;   &amp;lt;wsa:From&amp;gt;&lt;br /&gt;     &amp;lt;wsa:Address&amp;gt;urn:CompassionWeb&amp;lt;/wsa:Address&amp;gt;&lt;br /&gt;   &amp;lt;/wsa:From&amp;gt;&lt;br /&gt;  &amp;lt;/soap:Header&amp;gt;&lt;br /&gt;  &amp;lt;soap:Body&amp;gt;&lt;br /&gt;    &amp;lt;HelloWorld &lt;br /&gt;     xmlns="http://compassion.com/DemoServiceURI" /&amp;gt;&lt;br /&gt;  &amp;lt;/soap:Body&amp;gt;&lt;br /&gt;&amp;lt;/soap:Envelope&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Note that the MessageStreamID is created by the service consumer since this is the first message in the stream. The CreatorIdentity is the Windows account of the creator of the message and the culture is the culture setting on the client machine making the request. In this case the message will pass over HTTP and so the To element contains the .asmx address and the Action element the soapAction from the WSDL contract. The From element contains a URN that identifies the application that created the message. Since no ReplyTo element has been provided the reply if any will be sent to the URI from the which the message was received or that defined by the WSDL for the service. &lt;br /&gt;&lt;br /&gt;The reply to the above message would look as follows:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;soap:Envelope &lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   &lt;br /&gt; xmlns:xsd="http://www.w3.org/2001/XMLSchema"  &lt;br /&gt; xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" &lt;br /&gt; xmlns:ch=&lt;br /&gt; "http://schemas.compassion.com/common/headers/2005-04-05" &lt;br /&gt; xmlns:wsa=&lt;br /&gt; "http://schemas.xmlsoap.org/ws/2004/08/addressing"&amp;gt;    &lt;br /&gt;  &amp;lt;soap:Header&amp;gt;&lt;br /&gt; &amp;lt;ch:MessageStreamID&amp;gt;uuid:bbbb-cccc-dddd-eeee&lt;br /&gt; &amp;lt;/ch:MessageStreamID&amp;gt; &lt;br /&gt; &amp;lt;ch:DateTimeStamp&amp;gt;2005-04-05:T18:02:00&lt;br /&gt; &amp;lt;/ch:DateTimeStamp&amp;gt; &lt;br /&gt; &amp;lt;ch:CreatorIdentity&amp;gt;ci/serviceAccount&lt;br /&gt; &amp;lt;/ch:CreatorIdentity&amp;gt; &lt;br /&gt; &amp;lt;ch:Culture&amp;gt;en-US&amp;lt;/ch:Culture&amp;gt;&lt;br /&gt; &amp;lt;ch:UICulture&amp;gt;en-US&amp;lt;/ch:UICulture&amp;gt;&lt;br /&gt; &amp;lt;wsa:MessageID&amp;gt;uuid:gggg-cccc-dddd-eeee&lt;br /&gt; &amp;lt;/wsa:MessageID&amp;gt; &lt;br /&gt; &amp;lt;wsa:To&amp;gt;urn:CompassionWeb&amp;lt;/wsa:To&amp;gt;&lt;br /&gt; &amp;lt;wsa:Action&amp;gt;urn:CompassionWeb/ResponseMessage&lt;br /&gt; &amp;lt;/wsa:Action&amp;gt;  &lt;br /&gt; &amp;lt;wsa:From&amp;gt;&lt;br /&gt;  &amp;lt;wsa:Address&amp;gt;http://compassion.com/DemoServiceURI&lt;br /&gt;  &amp;lt;/wsa:Address&amp;gt;&lt;br /&gt; &amp;lt;/wsa:From&amp;gt;&lt;br /&gt; &amp;lt;wsa:RelatesTo&amp;gt;uuid:aaaa-cccc-dddd-eeee&lt;br /&gt; &amp;lt;/wsa:RelatesTo&amp;gt;&lt;br /&gt;   &amp;lt;/soap:Header&amp;gt;&lt;br /&gt;   &amp;lt;soap:Body&amp;gt;&lt;br /&gt;    &amp;lt;HelloWorldResponse &lt;br /&gt;      xmlns="http://compassion.com/DemoServiceURI" /&amp;gt;&lt;br /&gt;   &amp;lt;/soap:Body&amp;gt;&lt;br /&gt;&amp;lt;/soap:Envelope&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Here the MessageStreamID is copied from the request message and new DateTimeStamp and MessageID are created. The CreatorIdentity is now the account under which the service is executing. The To element contains the URN of the service consumer from the request message and the Action element includes an identifier that identifies the type of message being returned. The From element contains the URI of the service that returned the result and the RelatesTo element contains the MesssageID of the request message. &lt;br /&gt;&lt;br /&gt;In the second example that follows the service consumer includes a ReplyTo element that alerts the service provider as to where the response should be sent. In this case it is an MSMQ queue. The request queue is also specified in the To element. Note that the Action element still identifies the operation being invoked.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;soap:Envelope &lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   &lt;br /&gt; xmlns:xsd="http://www.w3.org/2001/XMLSchema"  &lt;br /&gt; xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" &lt;br /&gt; xmlns:ch=&lt;br /&gt; "http://schemas.compassion.com/common/headers/2005-04-05" &lt;br /&gt; xmlns:wsa=&lt;br /&gt; "http://schemas.xmlsoap.org/ws/2004/08/addressing"&amp;gt;    &lt;br /&gt; &amp;lt;soap:Header&amp;gt;&lt;br /&gt; &amp;lt;ch:MessageStreamID&amp;gt;uuid:bbbb-cccc-dddd-eeee&lt;br /&gt; &amp;lt;/ch:MessageStreamID&amp;gt; &lt;br /&gt; &amp;lt;ch:DateTimeStamp&amp;gt;2005-04-05:T18:00:00&amp;lt;/ch:DateTimeStamp&amp;gt; &lt;br /&gt; &amp;lt;ch:CreatorIdentity&amp;gt;ci/dfox&amp;lt;/ch:CreatorIdentity&amp;gt;&lt;br /&gt; &amp;lt;wsa:MessageID&amp;gt;uuid:aaaa-cccc-dddd-eeee&amp;lt;/wsa:MessageID&amp;gt;&lt;br /&gt; &amp;lt;wsa:To&amp;gt;urn:DIRECT=OS:compassion.com\PUBLIC\RequestQ&lt;br /&gt; &amp;lt;/wsa:To&amp;gt;&lt;br /&gt; &amp;lt;wsa:Action&amp;gt;http://compassion.com/DemoServiceURI&lt;br /&gt; &amp;lt;/wsa:Action&amp;gt;         &lt;br /&gt; &amp;lt;wsa:ReplyTo&amp;gt;              &lt;br /&gt;   &amp;lt;wsa:Address&amp;gt;&lt;br /&gt;     urn:DIRECT=OS:compassion.com\PUBLIC\ResponseQ        &lt;br /&gt;  &amp;lt;/wsa:Address&amp;gt;&lt;br /&gt; &amp;lt;/wsa:ReplyTo&amp;gt;&lt;br /&gt; &amp;lt;wsa:From&amp;gt;&lt;br /&gt;  &amp;lt;wsa:Address&amp;gt;urn:CompassionWeb&amp;lt;/wsa:Address&amp;gt;&lt;br /&gt; &amp;lt;/wsa:From&amp;gt;&lt;br /&gt;   &amp;lt;/soap:Header&amp;gt;&lt;br /&gt;  &amp;lt;soap:Body&amp;gt;&lt;br /&gt;    &amp;lt;HelloWorld &lt;br /&gt;     xmlns="http://compassion.com/DemoServiceURI" /&amp;gt;&lt;br /&gt;  &amp;lt;/soap:Body&amp;gt;&lt;br /&gt;&amp;lt;/soap:Envelope&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-112860417800863006?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/112860417800863006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=112860417800863006&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112860417800863006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112860417800863006'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/10/messaging-standards.html' title='Messaging Standards'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-112860414231954414</id><published>2005-10-06T06:08:00.000-07:00</published><updated>2005-10-07T05:04:22.370-07:00</updated><title type='text'>Schema Standards</title><content type='html'>One of the aspects of our services platform is &lt;a href="http://realsoa.blogspot.com/2005/05/service-communication.html"&gt;service communication&lt;/a&gt; which I discussed at a high level awhile back. One of the detailed aspects of this area is related to how schemas are defined for our contracts. &lt;br /&gt;&lt;br /&gt;Obviously, we're using XSD to define the schemas and we chose to build all the schemas within BizTalk. The reasons behind this are twofold: we wanted to standardize on a tool for building the schemas and we wanted to make sure the message contracts we defined would work in BizTalk since it is the central hub for all of our long running process services. &lt;br /&gt;&lt;br /&gt;What follows is a discussion of the related standards we used for creating schemas for use in the Compassion SOA that a namespace standard, a naming standard, a versioning standard, and an extensibility standard.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Namespace Standard&lt;/strong&gt;&lt;br /&gt;This namespace standard defines how namespaces will be used within the schemas produced for the Compassion SOA. &lt;br /&gt;&lt;br /&gt;The namespace used to identify schemas will follow a three part convention. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Part I:&lt;/strong&gt; A reference to http://schemas.compassion.com. All lowercase should be used.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Part II. &lt;/strong&gt;A domain specific identifier. For example constituent, common, child, etc. If there are sub-domains that need to be specified, use a backward slash as in constituent/profile. All lowercase should be used.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Part III.&lt;/strong&gt; The date on which the schema was finalized. The data is meant to uniquely identify this version of the schema. When a breaking change is made to the schema, a new schema should be created with a new date. Dates should be in the form yyyy-mm-dd, e.g. 2005-04-05.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note:&lt;/em&gt; A breaking change to the schema is defined as one where non-optional elements or attributes are added to the schema, where data types are changed, or where the document structure is incompatible with the previous version.&lt;br /&gt;&lt;br /&gt;Valid domain names that have been identified at this time include:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;constituent – includes constituent management schemas&lt;/li&gt;&lt;br /&gt;&lt;li&gt;common – includes common schemas such as headers, exceptions, and workflow&lt;/li&gt;&lt;br /&gt;&lt;li&gt;child – includes child management schemas&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;Examples using this three part convention include:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;http://schemas.compassion.com/constituent/2005-03-28&lt;br /&gt;http://schemas.compassion.com/constituent/2005-05-05 &lt;br /&gt;http://schemas.compassion.com/common/headers/2005-04-05  &lt;br /&gt;http://schemas.compassion.com/constituent/profile/2005-03-28&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Naming Standard&lt;/strong&gt;The naming standard is in place in order to specify how elements and attributes are named. It consists of the following:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Element names should use Pascal casing (upper case first letter of each word)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Attribute names should use Camel casing (lowercase first letter of the first word, upper case first letter of all other words&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Attributes should be used for identifying information within an element. For example identifiers such as ConstituentID would be modeled as an attribute&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The ID suffix should be uppercase when used&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Versioning Standard&lt;/strong&gt;&lt;br /&gt;The versioning standard is in place in order to support visibility to consumers of documents produced using the schema for non-breaking changes. For example, if a schema includes a new optional element or attribute, the versioning standard allows a consumer of the schema to note the version in order to dynamically add the appropriate element. &lt;br /&gt;&lt;br /&gt;The versioning standard mandates the inclusion of the following attribute in the root node of the schema:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;xs:attribute name="schemaVersion" type="xs:decimal" /&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;By adding this attribute documents can be created that specify the version number in addition to the unique identifier specified in the namespace. &lt;br /&gt;&lt;br /&gt;When a new schema is created, documents created using the schema should default the schemaVersion to 1.0. As revisions are published the latest schemaVersion will be placed in instance documents, for example, 1.2. Since the version numbers are not visible within the schemas but only in the instance documents, the schema repository will track older versions of the schema.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Extensibility Standard&lt;/strong&gt;&lt;br /&gt;In order to provide extensibility for consumers of schemas as the schema evolves the following extensibility standard has been created. The following element should be added to the root element of the schema as well as any other elements where extensibility may be expected.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;xsd:any namespace="##any" processContents="lax"&lt;br /&gt;minOccurs="0" maxOccurs="unbounded"/&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This element insures that additional elements of any number from any namespace may occur within this element and that a consumer is not obligated to validate the contents ("lax"). &lt;br /&gt;&lt;br /&gt;The second aspect of this standard is that the root element should also contain the following element.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;xs:anyAttribute namespace="##any" processContents="lax"/&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This allows additional attributes to be placed in the root element. This standard has implications for the way in which .NET schema consumers behave. Using this standard, .NET classes created using the Xml Schemas/DataTypes Support Utility (xsd.exe) will include arrays of XmlElement and XmlAttribute objects that are decorated with the XmlAnyElementAttribute and the XmlAnyAttributeAttribute. To populate these elements consumers will then need to create these types and add them to the array. While this provides extensibility, the extension objects are not strongly typed. See the examples section for the sample code to do this.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br /&gt;An example schema follows:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;xs:schema &lt;br /&gt; xmlns=&lt;br /&gt;  "http://schemas.compassion.com/constituent/2005-03-01"&lt;br /&gt; targetNamespace=&lt;br /&gt;   "http://schemas.compassion.com/constituent/2005-03-01"&lt;br /&gt; xmlns:xs="http://www.w3.org/2001/XMLSchema"&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name="Constituent"&amp;gt;&lt;br /&gt;    &amp;lt;xs:complexType&amp;gt;&lt;br /&gt;      &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;        &amp;lt;xs:element name="Name" type="xs:string" &lt;br /&gt;          minOccurs ="1" /&amp;gt;&lt;br /&gt;        &amp;lt;xs:element name="Address1" type="xs:string" &lt;br /&gt;          minOccurs ="1" /&amp;gt;&lt;br /&gt;        &amp;lt;xs:any namespace="##any" processContents="lax" &lt;br /&gt;           minOccurs="0" maxOccurs="unbounded"/&amp;gt;&lt;br /&gt;      &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;      &amp;lt;xs:attribute name="schemaVersion" &lt;br /&gt;        type="xs:decimal" /&amp;gt;&lt;br /&gt;      &amp;lt;xs:attribute name="ConstituentId" &lt;br /&gt;        type="xs:long" /&amp;gt;&lt;br /&gt;      &amp;lt;xs:anyAttribute namespace="##any" &lt;br /&gt;        processContents="lax" /&amp;gt;&lt;br /&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;  &amp;lt;/xs:element&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Note the presence of schemaVersion as well as the namespace that adheres to the Namespace Standards defined above and the extensibility points.&lt;br /&gt;&lt;br /&gt;An instance document using this schema would then look as follows.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;Constituent&amp;gt;&lt;br /&gt;  xmlns=&lt;br /&gt;   "http://schemas.compassion.com/constituent/2005-03-01"&lt;br /&gt;  ConstituentId="1234" schemaVersion="1.0"&amp;gt;&lt;br /&gt;  &amp;lt;Name&amp;gt;John Jones&amp;lt;/Name&amp;gt;&lt;br /&gt;  &amp;lt;Address1&amp;gt;555 Elm Street&amp;lt;/Address1&amp;gt;&lt;br /&gt;&amp;lt;/Constituent&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;If a breaking change occurs, for example, an Address2 element is added that is not optional (it’s minOccurs attribute is set to "1") then the new schema would be defined as follows.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;xs:schema &lt;br /&gt; xmlns=&lt;br /&gt;  "http://schemas.compassion.com/constituent/2005-04-01"&lt;br /&gt; targetNamespace=&lt;br /&gt;"http://schemas.compassion.com/constituent/2005-04-01"&lt;br /&gt; xmlns:xs="http://www.w3.org/2001/XMLSchema"&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name="Constituent"&amp;gt;&lt;br /&gt;    &amp;lt;xs:complexType&amp;gt;&lt;br /&gt;      &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;        &amp;lt;xs:element name="Name" type="xs:string" &lt;br /&gt;          minOccurs ="1" /&amp;gt;&lt;br /&gt;        &amp;lt;xs:element name="Address1" type="xs:string" &lt;br /&gt;          minOccurs ="1" /&amp;gt;&lt;br /&gt;        &amp;lt;xs:element name="Address2" type="xs:string" &lt;br /&gt;          minOccurs ="1" /&amp;gt;&lt;br /&gt;        &amp;lt;xsd:any namespace="##any" processContents="lax" &lt;br /&gt;           minOccurs="0" maxOccurs="unbounded"/&amp;gt;&lt;br /&gt;      &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;      &amp;lt;xs:attribute name="schemaVersion" &lt;br /&gt;        type="xs:decimal" /&amp;gt;&lt;br /&gt;      &amp;lt;xs:attribute name="ConstituentId" &lt;br /&gt;        type="xs:long" /&amp;gt;&lt;br /&gt;      &amp;lt;xsd:anyAttribute namespace="##any" &lt;br /&gt;        processContents="lax" /&amp;gt;&lt;br /&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;  &amp;lt;/xs:element&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Note that the targetNamespace has been changed since the schema contains a new element. &lt;br /&gt;&lt;br /&gt;However, if the schema published under the http://schemas.compassion.com/constituent/2005-03-01 namespace is modified to support an optional Address2 (minOccurs = "0"), then documents created using the new version should include the incremented schemaVersion, for example, to 1.5 as in the following example document.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;Constituent&amp;gt; &lt;br /&gt;  xmlns=&lt;br /&gt;   "http://schemas.compassion.com/constituent/2005-03-01"&lt;br /&gt;  ConstituentId="1234" schemaVersion="1.5"&amp;gt;&lt;br /&gt;  &amp;lt;Name&amp;gt;John Jones&amp;lt;/Name&amp;gt;&lt;br /&gt;  &amp;lt;Address1&amp;gt;555 Elm Street&amp;lt;/Address1&amp;gt;&lt;br /&gt;  &amp;lt;Address2&amp;gt;Apt 5678&amp;lt;/Address2&amp;gt;&lt;br /&gt;&amp;lt;/Constituent&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;In this way consumers of the new document will be valid under the original schema (1.0) through the extensibility points and the document can be identified as varying from the original through the schemaVersion. Documents created under the original version of the schema (1.0) will be valid under the new version since Address2 is optional.&lt;br /&gt;&lt;br /&gt;In order to illustrate how the extensibility portion of the standard works consider the following code. &lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;XmlTypeAttribute([Namespace]:= _&lt;br /&gt;"http://schemas.compassion.com/constituent/2005-03-01"),  _ &lt;br /&gt;   XmlRootAttribute([Namespace]:= _&lt;br /&gt;"http://schemas.compassion.com/constituent/2005-03-01", _ &lt;br /&gt;  IsNullable:=false)&amp;gt;  _&lt;br /&gt;Public Class Constituent &lt;br /&gt;    &amp;lt;XmlElementAttribute()&amp;gt;  _&lt;br /&gt;    Public Name As String&lt;br /&gt;&lt;br /&gt;    &amp;lt;XmlElementAttribute()&amp;gt;  _&lt;br /&gt;    Public Address1 As String&lt;br /&gt;&lt;br /&gt;    &amp;lt;XmlAnyElementAttribute()&amp;gt;  _&lt;br /&gt;    Public Any() As XmlElement&lt;br /&gt;&lt;br /&gt;    &amp;lt;XmlAttributeAttribute()&amp;gt;  _&lt;br /&gt;    Public schemaVersion As Decimal&lt;br /&gt;&lt;br /&gt;    &amp;lt;XmlIgnoreAttribute()&amp;gt;  _&lt;br /&gt;    Public schemaVersionSpecified As Boolean&lt;br /&gt;    &amp;lt;XmlAttributeAttribute()&amp;gt;  _&lt;br /&gt;    Public ConstituentId As Long&lt;br /&gt;&lt;br /&gt;    &amp;lt;XmlIgnoreAttribute()&amp;gt;  _&lt;br /&gt;    Public ConstituentIdSpecified As Boolean&lt;br /&gt;&lt;br /&gt;    &amp;lt;XmlAnyAttributeAttribute()&amp;gt;  _&lt;br /&gt;    Public AnyAttr() As XmlAttribute&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;This code was generated using the schema shown previously using the xsd.exe utility. As you can see the tool generated an array of XmlElement objects called Any and an array of XmlAttribute objects called AnyAttr. Client code that needs to populate the new version of the schema (1.5) with the optional Address2 element would then need to do the following.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Dim c As New Constituent&lt;br /&gt;&lt;br /&gt;' Populate the document&lt;br /&gt;c.Name = "Willie Mays"&lt;br /&gt;c.Address1 = "Candlestick Park"&lt;br /&gt;c.ConstituentId = "1234"&lt;br /&gt;c.schemaVersion = 1.5&lt;br /&gt;&lt;br /&gt;' Create the Address2 element&lt;br /&gt;Dim xdoc As New XmlDocument&lt;br /&gt;Dim x1 As XmlElement = xdoc.CreateElement("Address2", _&lt;br /&gt;"http://schemas.compassion.com/constituent/2005-03-01")&lt;br /&gt;Dim x2 As XmlText = &lt;br /&gt; xdoc.CreateTextNode("San Francisco Giants")&lt;br /&gt;Console.WriteLine(x1.NamespaceURI)&lt;br /&gt;&lt;br /&gt;' Append it to the document&lt;br /&gt;x1.AppendChild(x2)&lt;br /&gt;&lt;br /&gt;' Add it to the Constituent&lt;br /&gt;Dim ext(0) As XmlElement&lt;br /&gt;ext(0) = x1&lt;br /&gt;c.Any = ext&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The disadvantage to this approach this approach is that the code required to add the additional element is fairly cumbersome. However, doing so allows the Constituent class to remain unchanged in the event that it resides in a different assembly that will not be recompiled and redistributed to clients.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-112860414231954414?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/112860414231954414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=112860414231954414&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112860414231954414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112860414231954414'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/10/schema-standards.html' title='Schema Standards'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-112860258451411277</id><published>2005-10-06T05:30:00.000-07:00</published><updated>2005-10-06T05:43:04.523-07:00</updated><title type='text'>Too Small To Ignore</title><content type='html'>Yesterday the President and CEO of Compassion Wes Stafford spoke to the entire organization about his new book &lt;em&gt;&lt;a href="http://www.toosmalltoignore.com/"&gt;Too Small to Ignore: Why Children are the Next Big Thing&lt;/a&gt;&lt;/em&gt; published by Waterbrook Press. &lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.compassion.com/NR/rdonlyres/eqoa4t7dzvuqzyikmaerahyorypoxf4kcqwanaath2e6c5die5exm7u7i3dyuowx4rkvhd4fkpv4juxfa6gejmcf4kg/compassionchildadvocacyWessStaffordtoosmalltoignorechristianbook.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;The book is a wakeup call that brings home the message that children matter and that those who have the power (which ultimately includes all of us) should use that power to be the voice for improverished children around the world. Wes grew up in rural west Africa (Ivory Coast) as the son of missionaries and lived among the people that Compassion now serves. He has a unique insight into the problem and the face of poverty that he also shares in the book in recounting some of his journey. &lt;br /&gt;&lt;br /&gt;The book will hit stores October 18th but you can preorder from the link above.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-112860258451411277?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/112860258451411277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=112860258451411277&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112860258451411277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112860258451411277'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/10/too-small-to-ignore.html' title='Too Small To Ignore'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-112846189463532973</id><published>2005-10-04T14:24:00.000-07:00</published><updated>2005-10-04T15:11:07.843-07:00</updated><title type='text'>Transaction Handling in EDAF</title><content type='html'>In my previous post I mentioned that I'd share a bit about how we modified EDAF v1.1 for our services platform here at Compassion. There are several ways we've done this that include:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Modifying the service interface adapters to use our messaging standards&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Modifying the exception reporting framework to log exceptions to our central logging store&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Creating a base class for business actions to include common code&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Modifying the TransactionHandler to support a model where business actions do not throw exceptions and transactions can span the invocations of business actions&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;It is this final one that I'll explore today, the others will have to wait for a future post.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Background&lt;/strong&gt;&lt;br /&gt;There have been two major efforts at creating web service specifications in the industry as documented by &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321180860/qid=1128462565/sr=8-4/ref=pd_bbs_4/102-8364086-7839344?v=glance&amp;s=books&amp;n=507846"&gt;Newcomer and Lowow&lt;/a&gt; in chapter 10:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;WS-Transactions&lt;/strong&gt;. This includes a family of specifications developed by Microsoft, BEA, and IBM that includes WS-AtomicTransaction, WS-BusinessActivity, and WS-Coordination.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;WS-Composite Application Framework&lt;/strong&gt;. This is a family of specifications developed by Arjuna, IONA, Oracle, Fujitsu, and Sun and includes WS-Context, WS-CoordinationFramework, and WS-TransactionManagement.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;These specifications are similar and have considerable overlap. For example, in both cases "participants in a transaction register with a coordinator and specify the protocol type so that the coordinator can drive the appropriate protocol for use." Both can support various transaction processing requirements including two-phase commit, compensation, and business process transactions. The hope is that these will merge into a single specification in the future.&lt;br /&gt;&lt;br /&gt;However, in our evaluation of these specifications it was apparent that there is no infrastructure in place to support either. In other words, there would need to be a set of code in place that interpreted the SOAP header information specified in these various specifications and performed the registration as well as controlled the transaction. Support for WS-Transaction will be built into Indigo within Win/FX, however. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Approach&lt;/strong&gt;&lt;br /&gt;Because it is not practical for Compassion to implement the kind of infrastructure required, the approach we’ve taken is to modify and use the Transaction Handler present in EDAF to implement Component Services transactions across Business Actions. &lt;br /&gt;&lt;br /&gt;The Transaction Handler within EDAF takes advantage of EnterpriseServices (COM+) in the .NET Framework to implement transaction support. The handler itself uses an object named TransactionRequired, which is registered with COM+ by the TransactionHandlerInstaller assembly. The TransactionRequired object is configured to require transactions and set the isolation level to Serializable. Since this is a stacked around handler the target will always be included in the transaction. In addition, any handlers that are wrapped by this handler will also be included in the transaction. If execution is successful, the transaction is committed. If an exception is thrown, then the transaction is stopped. This handler can then be placed within the Service Implementation pipeline &lt;br /&gt;&lt;br /&gt;In our architecture services report &lt;em&gt;both&lt;/em&gt; business and system exceptions within an Exceptions element that is returned within the SOAP body as in the example below. &lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;Exceptions &lt;br /&gt;  xmlns="http://schemas.compassion.com/common/&lt;br /&gt;    exceptions/2005-03-01"&amp;gt;&lt;br /&gt;  &amp;lt;Exception Type="System" xmlns=""&amp;gt;&lt;br /&gt;     &amp;lt;DateTimestamp&amp;gt;0001-01-01T00:00:00.0000000-07:00&lt;br /&gt;     &amp;lt;/DateTimestamp&amp;gt;&lt;br /&gt;     &amp;lt;Code&amp;gt;Compassion.Common.Data&amp;lt;/Code&amp;gt;&lt;br /&gt;     &amp;lt;Message&amp;gt;Could not create data reader from &lt;br /&gt;      statement GetCon&amp;lt;/Message&amp;gt;&lt;br /&gt;     &amp;lt;StackTrace&amp;gt; at Compassion.Common.Data.&lt;br /&gt;      DataFactory._throwException…&lt;br /&gt;     &amp;lt;/StackTrace&amp;gt;&lt;br /&gt;  &amp;lt;/Exception&amp;gt;&lt;br /&gt;  &amp;lt;Exception Type="Business" xmlns=""&amp;gt;&lt;br /&gt;      &amp;lt;DateTimestamp&amp;gt;2005-05-18T09:09:54.9242939-06:00&lt;br /&gt;      &amp;lt;/DateTimestamp&amp;gt;&lt;br /&gt;           &amp;lt;Source&amp;gt;Execute&amp;lt;/Source&amp;gt;&lt;br /&gt;           &amp;lt;Code&amp;gt;INVALID_ID&amp;lt;/Code&amp;gt;&lt;br /&gt;           &amp;lt;Message&amp;gt;Constituent with ID [353594] &lt;br /&gt;              was not found.&lt;br /&gt;           &amp;lt;/Message&amp;gt;&lt;br /&gt;           &amp;lt;StackTrace&amp;gt; at Compassion.Services.&lt;br /&gt;              Actions.Constituent…&lt;br /&gt;           &amp;lt;/StackTrace&amp;gt;&lt;br /&gt;   &amp;lt;/Exception&amp;gt;&lt;br /&gt;&amp;lt;/Exceptions&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;As a result, the Business Actions we develop will not throw .NET exceptions to their callers and in turn when using the TransactionHandler transactions will not typically be rolled back since the TransactionRequired class is marked with an AutoComplete attribute and so will only rollback when an exception is thrown from within one of the business actions or handlers it is encapsulating.&lt;br /&gt;&lt;br /&gt;To address this situation we’ve modified the TransactionRequired class within EDAF to remove the AutoComplete attribute and instead rollback or commit transactions using the ContextUtil.SetAbort and ContextUtil.SetComplete methods respectively. The class will do this when it finds that the TransactionValid key (a key the handler itself initializes) in the EDAF Context is set to false. This technique is analogous to the way in which COM+ manages transactions internally. Each component (in this case business action) that participates in the transaction "votes" on its outcome by either setting the flag to false signifying that the business action is not happy and the transaction should be rolled back or doing nothing which signifies that the business action is happy and the transaction should continue.&lt;br /&gt;&lt;br /&gt;Transaction context will flow across invocations of business actions since the TransactionRequired will have its transactional support set to Required as shown in the following dialog.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/Tx1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/2568/246/320/Tx1.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In this way, the first business action that is invoked will act as the root of the distributed transaction. Each subsequent business action will be wrapped in another instance of the Transaction Handler and will enlist in the already started transaction. If one of the nested business actions sets its TransactionValid flag to false, its Transaction Handler will call ContextUtil.SetAbort thereby aborting the entire distributed transaction and rolling back the work done for all business actions in the call stack. This is illustrated in the following diagram where the step numbers denote the timing.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/tx.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/2568/246/400/tx.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Implications&lt;/strong&gt;&lt;br /&gt;The implications of this technique are threefold:&lt;br /&gt;&lt;br /&gt;First, developers of business actions are required to set the TransactionValid flag to false when they wish their database changes to be rolled back. The general pattern for doing so is shown below.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;public void Execute(IContext objContext)&lt;br /&gt;{&lt;br /&gt; try&lt;br /&gt; {&lt;br /&gt;  // Perform database writes or call&lt;br /&gt;  // other business actions&lt;br /&gt; }&lt;br /&gt; catch (Exception ex)&lt;br /&gt; {&lt;br /&gt;  // Handle System Exceptions and create Exception &lt;br /&gt;  // elements to add to the response&lt;br /&gt; }&lt;br /&gt; finally&lt;br /&gt; {&lt;br /&gt;  // Inspect response and create business Exception&lt;br /&gt;  // elements to add to the response&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;// Vote on the outcome of the transaction&lt;br /&gt; if (objResp.Exceptions.Length&gt;0)&lt;br /&gt;  if (objContext["TransactionValid"] != null)&lt;br /&gt;objContext["TransactionValid"] == false;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Here, the entire activity of the business action is encapsulated in a try/catch block. System and business exceptions are detected either through catching exceptions thrown from the data access layer or by inspecting the contents of the response returned from the data access layer. &lt;br /&gt;&lt;br /&gt;It should be noted that in our implementation we've abstracted the setting of the TransactionValid flag in a base class from which all business action classes inherit.&lt;br /&gt;&lt;br /&gt;Using this approach implies that the business action will be implemented within a Service Implementation pipeline in which the Transaction Handler is configured. The work done in the try block will then be rolled back when the Transaction Handler aborts the transaction. Therefore business actions should not use local transactional control (they should not be starting and committing local transactions). &lt;br /&gt;&lt;br /&gt;Secondly, this architecture implies that in order for the transaction context to flow across business action requests the business action must be invoked using the in-process service interface adapter. In other words, if business action A invokes business action B and the work from the both actions needs to be part of a single distributed transaction, action A must invoke action B using the in-process adapter. This is the case since distributed transaction cannot flow across the other interface adapters in EDAF which include web services, MSMQ, and .NET Remoting.&lt;br /&gt;&lt;br /&gt;For example, a business action could invoke the SelectEmailRequest business action using the in process adapter like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;InProcDispatchingAdapter objDA = &lt;br /&gt;  new InProcDispatchingAdapter();&lt;br /&gt;Request objRequest = new Request();&lt;br /&gt;objRequest.ServiceActionName = "UpdateAddress";&lt;br /&gt;&lt;br /&gt;objRequest.Payload = &lt;br /&gt;  XmlSerializerHelper.SerializeToXml(objUpdateRequest);&lt;br /&gt;&lt;br /&gt;Context objDAContext = new Context(objRequest);&lt;br /&gt;objDAContext.Add("ValidateOnly",this.ValidateOnly);&lt;br /&gt;&lt;br /&gt;objDA.Submit(objDAContext);&lt;br /&gt;&lt;br /&gt;//get the response.&lt;br /&gt;AddressUpdateResponse objCompletedResponse = &lt;br /&gt;  (AddressUpdateResponse)&lt;br /&gt;  XmlSerializerHelper.Deserialize(((XmlDocument)&lt;br /&gt;  objDAContext.Response.Payload).InnerXml,&lt;br /&gt;   typeof(AddressUpdateResponse));&lt;br /&gt;&lt;br /&gt;//append any exceptions.&lt;br /&gt;this.AppendExceptions(objCompletedResponse.Exceptions);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Here you’ll notice that a new Context object is created for the request to the UpdateAddress business action. In this case each business action will have its own Context object in which the Transaction Handler will check for and use the TransactionValid flag. &lt;br /&gt;&lt;br /&gt;The third implication of this approach is that service consumers need to be aware that there is no way in our current architecture of flowing transaction context across two or more service invocations. For example, if a service consumer uses a service agent to invoke the UpdateConstituent operation and then uses the same service agent to invoke CreateConstituent, these two invocations cannot participate in the same distributed transaction. This is the case since the service agents will invoke the services using SOAP over HTTP or MSMQ, neither of which offer distributed transactions at present. The thought is that in the future support for transactions across service calls will be supported by the Indigo framework in Win/FX using WS-Transactions, which can then be integrated into the service agent framework.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-112846189463532973?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/112846189463532973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=112846189463532973&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112846189463532973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112846189463532973'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/10/transaction-handling-in-edaf.html' title='Transaction Handling in EDAF'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-112716643707117532</id><published>2005-09-19T14:07:00.000-07:00</published><updated>2005-09-19T14:55:26.183-07:00</updated><title type='text'>Selecting EDAF</title><content type='html'>When I left off at the end of May I was discussing EDAF and how we used it to implement our services. What follows is a description of EDAF and how we use it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In order to implement Activity (some of them), Entity, and Infrastructure Services we've taken the approach of using the guidance created by the Microsoft Patterns and Practices Group (PAG). The collection of Microsoft best practices in this area comes in the form of the Enterprise Development Reference Architecture (EDRA) formerly known as "Shadowfax". This .NET code base is designed to provide architectural guidance to organizations moving to service orientation by including the following:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;An extensible application framework called the Enterprise Development Application Framework (EDAF)&lt;/li&gt;&lt;li&gt;Four QuickStart applications to familiarization with EDRA&lt;/li&gt;&lt;li&gt;An application template and supporting documentation used to build new services&lt;/li&gt;&lt;li&gt;The Global Bank Reference Implementation (GBRI) that uses EDRA to implement an online banking scenario&lt;/li&gt;&lt;li&gt;A good base of documentation on which to work&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All of the information for EDRA including its releases can be found on its GotDotNet workspace at &lt;a href="http://workspaces.gotdotnet.com/shadowfx"&gt;http://workspaces.gotdotnet.com/shadowfx&lt;/a&gt;. In addition, more information can be found on the Channel 9 EDRA Wicki at &lt;a href="http://channel9.msdn.com/wiki/default.aspx/Channel9.EDRAWiki"&gt;http://channel9.msdn.com/wiki/default.aspx/Channel9.EDRAWiki&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For the CI-SOA (Compassion International SOA) the final released version, 1.1, is being used. In addition the CI-SOA will integrate several tools included with EDRA in the future.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;UI support for Visual Studio&lt;/li&gt;&lt;li&gt;A service agent&lt;/li&gt;&lt;li&gt;A configuration editing tool&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;At a high level, the EDAF has four primary goals: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Separating the service interface from the service implementation&lt;/li&gt;&lt;li&gt;Separating the business logic from the cross-cutting concerns mentioned previously&lt;/li&gt;&lt;li&gt;Separating the business logic from the underlying transport so that different transports can be used to access a service&lt;/li&gt;&lt;li&gt;Develop a stable service interface to ensure resiliency when services are deployed&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In evaluating whether or not the EDAF would be used for the CI-SOA the project, the other options included: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Implementing Entity and Infrastructure services as simple .ASMX&lt;/strong&gt;. This is the approach Microsoft recommends in order to make it as simple as possible to move to the new Indigo service framework when it is released (for example See David Chappell’s overview of Indigo at &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnlong/html/introindigov1-0.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnlong/html/introindigov1-0.asp&lt;/a&gt;) in the spring of 2006. Specifically, the guidance offered was in opposition to implementing services today using Enterprise Services or .NET Remoting. Using straightforward .ASMX, however, does not provide the infrastructure for duplicate message handling (&lt;em&gt;idempotent&lt;/em&gt; messaging), message logging, performance monitoring, access through multiple interfaces, and other cross-cutting concerns. Since these are standards in our Services Platform that the project team will implement, and since it was not practical to wait for Indigo in order to implement since the first deliverable in August 2005, it was decided that the EDAF provided the core framework needed to build services. The thought is that the separation of service interface from service implementation that the EDAF provides will allow the business logic of Compassion services to be re-factored into Indigo services when it is deemed practical in the future.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Implementing Entity and Infrastructure services as BizTalk orchestrations&lt;/strong&gt;. The other option that was considered was implementing all services as BizTalk Orchestrations and exposing those services using the BizTalk orchestration web publishing wizard as illustrated in the following diagram.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p align="center"&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/edaf1.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2568/246/320/edaf1.jpg" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The advantages of doing so include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The fact that some of the cross-cutting concerns such as logging and performance monitoring are already implemented within BizTalk Server&lt;/li&gt;&lt;li&gt;There is expertise in the industry regarding BizTalk and how to build orchestrations along with examples and schemas&lt;/li&gt;&lt;li&gt;It provides a one-stop approach to upgrading&lt;/li&gt;&lt;li&gt;Future interoperability with technologies such as Indigo will be packaged into upgrades of BizTalk server. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The disadvantages of doing so include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A complete dependency on BizTalk for all service development which reduces flexibility&lt;/li&gt;&lt;li&gt;The need to build façade type orchestrations that may become complex in order to expose multiple operations in a single web service&lt;/li&gt;&lt;li&gt;The ability to perform maintenance and upgrade pieces of the architecture is reduced&lt;/li&gt;&lt;li&gt;The need to build out other cross-cutting concerns within BizTalk including duplicate message handling, and authorization&lt;/li&gt;&lt;li&gt;The need to roll out a set of services in a Partner Country or Field Office requires that BizTalk server be deployed and maintained in that environment. Services built using EDAF would require a smaller footprint and investment in terms of licensing. At present, however, there is no small-footprint option for deploying process services. We assume that if those require orchestrations BizTalk would be installed in the field.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In final analysis, the decision was made to take advantage of the strengths of BizTalk which include orchestrating long running business processes and not attempt to shoe-horn the implementation of more straightforward request-response style services into it. The only caveat to the above is that Activity Services that require transactional coordination among Entity Services or the ability to retry operations in the event of a data store being unavailable will be implemented as BizTalk orchestrations. The reason is that transactional coordination across service invocations is not implemented in the standard platform shipped by Microsoft (for example through support of WS-AtomicTransaction) nor is it a part of the EDAF (the EDAF supports compensating business actions and atomic transactions within a service invocation but not across service invocations). It will be a part of Indigo, however, and so Activity Services should be able to be implemented using Indigo in the future.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In order to satisfy these goals the EDAF implements two primary patterns.&lt;br /&gt;&lt;br /&gt;&lt;a name="_Toc100448462"&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Interception Pattern&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt;The EDAF abstracts how the service is invoked (its service implementation) from the core logic of the service (its service implementation) as shown below. This allows services to be invoked in a variety of scenarios, for example by web sites, Windows applications, Smart Device applications, and even by a BizTalk orchestration that places the message in a queue. This architecture also allows organizations to customize their deployment across several severs although typically the service interface will use the Web Services interface transport and the service implementation the InProc dispatching transport.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p align="center"&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/edaf2.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2568/246/320/edaf2.jpg" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The space between the client and the service interface and the service interface and service implementation includes the notion of transports and adapters. The transports abstract the invocation of the service (interface transports) and its implementation (dispatching transports) while the adapters are responsible for receiving the message and initiating message processing.&lt;br /&gt;&lt;br /&gt;The interface transports that ship with EDAF include Web Services, .NET Remoting, and Message Queuing. The dispatching transports include Web Services, Message Queueing, DCOM, and in-process (InProc). Each transport, with the exception of InProc needs a host and so for web services the host is IIS/ASP.NET. For .NET Remoting and MSMQ the EDAF provides both a Windows Service called TransportService.exe and a console application called TransportConsole.exe. &lt;/p&gt;&lt;p&gt;Organizations can also implement their own interface transport by creating a class that implements the ITransportListenerController interface and hosting it the provided hosts or an executable. This interface includes simple Start and Stop methods that are called by the EDAF to begin and to quit listening for requests respectively. For example, one could create an FTP Transport by hosting a component in a Windows Service that "listens" for requests by polling the folder used by an FTP site.&lt;br /&gt;&lt;br /&gt;Each of the interface transports has an associated adapter that is responsible for extracting the request message from the transport and creating the EDAF Context object which is a kind of wrapper object that contains all of the information needed to process the request. The Context is then passed into the service interface. Likewise, each dispatching transport has an adapter that retrieves the Context object and passes it into the service implementation. Each adapter is customized for its transport, for example, the Web Services interface transport’s adapter is implemented as a SOAP extension.&lt;br /&gt;&lt;br /&gt;This pattern is an integral part of EDAF and will be used when implementing services in order to separate the service interfaces from the service implementations. By doing so the service implementations can be invoked from a variety of service interfaces. &lt;/p&gt;&lt;p&gt;&lt;a name="_Toc100448463"&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Pipeline Pattern&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt;One of the major goals of the EDAF is to separate cross-cutting concerns such as logging, security, transactional behavior, and event notification from the business logic. To achieve this goal both the service interface and the service implementation include the concept of pipelines. A pipeline consists of a chain of handlers that each implement one of the cross-cutting functionalities as shown below. This is an implementation of the well-known Chain of Responsibility pattern. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p align="center"&gt;&lt;a href="http://photos1.blogger.com/blogger/2568/246/1600/edaf3.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2568/246/320/edaf3.jpg" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;These pipelines are executed by the adapters and passed the Context object discussed in the previous section. When all of the handlers have been executed the pipeline finally executes a target object. The target object is specific to what it will execute, for example, whether the target is to pass the Context object to the dispatching transport or whether to a business action.&lt;br /&gt;&lt;br /&gt;The service interface pipeline shown in the diagram is transport-specific and typically focuses on boundary concerns such as authentication, request monitoring, validating the request message, and handling duplicate request messages by returning a cached result (idempotence). As a result, the service interface pipeline might be configured to include the AuthenticationInfrastructure and AuthorizationInfrastructure handlers to perform client authentication and authorization using the Windows identity and either Active Directory or NTLM groups.&lt;br /&gt;&lt;br /&gt;The pipelines and the handlers that are included are configured in the EDAF configuration file making these easy to adjust and turn on and off as needed.&lt;br /&gt;&lt;br /&gt;The service implementation handlers on the other hand usually include service specific behaviors such as raising business events using WMI, logging requests, implementing transactions, or transforming messages. The following table shows the handlers that ship with the EDAF.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;strong&gt;Handler&lt;/strong&gt;&lt;br /&gt;ClientTrace                  &lt;br /&gt;Returns a trace of the execution of the request with the response&lt;br /&gt;&lt;br /&gt;AuthorizationDatabase        &lt;br /&gt;Performs authorization of the request using a SQL database&lt;br /&gt;&lt;br /&gt;DuplicateHandling            &lt;br /&gt;Implements once-only processing of a message&lt;br /&gt;&lt;br /&gt;AppInstrumentationExecution  &lt;br /&gt;Monitors the time taken to execute the request from this point forward&lt;br /&gt;&lt;br /&gt;AuthenticationIdentity       &lt;br /&gt;Trusts the current credentials passed in with the request&lt;br /&gt;&lt;br /&gt;AuthenticationInfrastructure &lt;br /&gt;Ensures that the identity is authenticated using Windows&lt;br /&gt;&lt;br /&gt;AuthorizationInfrastructure  &lt;br /&gt;Authorizes a request using Windows groups&lt;br /&gt;&lt;br /&gt;AppInstrumentation           &lt;br /&gt;Updates performance monitor counters&lt;br /&gt;&lt;br /&gt;MessageTransformation        &lt;br /&gt;Uses an XSLT to transform a message&lt;br /&gt;&lt;br /&gt;PasswordAuthorizationHandler&lt;br /&gt;Performs user name and password authentication&lt;br /&gt;&lt;br /&gt;PublishBusinessEvent         &lt;br /&gt;Publishes a business event&lt;br /&gt;&lt;br /&gt;SignedMessageAuthentication  &lt;br /&gt;Uses a public key to verify the signature of an XML message&lt;br /&gt;&lt;br /&gt;SyntacticValidation          &lt;br /&gt;Transforms the message into a strongly-typed message&lt;br /&gt;&lt;br /&gt;ExecutionTimeout             &lt;br /&gt;Monitors the execution of the request beyond this handler and times it&lt;br /&gt;&lt;br /&gt;Transaction                  &lt;br /&gt;Starts a new COM+ transaction&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Handlers also provide an extensibility point where the project team will insert custom processing in the pipeline. The EDAF includes three handlers interfaces that include IAtomicHandler for basic process, IStatefulAroundHandler for handlers that need to execute in the same stack frame, and IStatelessAroundHandler for handlers that execute both before and after the target is executed.&lt;br /&gt;&lt;br /&gt;This pattern is an integral part of EDAF and will be used to add handlers that participate in the processing of service requests and responses. The cross-cutting concerns mentioned above are implemented with handlers.&lt;br /&gt;&lt;br /&gt;In the next post I'll take a look at how we customized EDAF to fit our Services Platform.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-112716643707117532?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/112716643707117532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=112716643707117532&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112716643707117532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112716643707117532'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/09/selecting-edaf.html' title='Selecting EDAF'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-112716402329548442</id><published>2005-09-19T13:41:00.000-07:00</published><updated>2005-09-19T14:07:03.303-07:00</updated><title type='text'>Real SOA!</title><content type='html'>I know it's been a long time since I published an update on our SOA implementation here at &lt;a href="http://www.compassion.com"&gt;Compassion International&lt;/a&gt;. However, it's been a busy summer (and I've been doing alot of &lt;a href="http://www.hardballtimes.com/main/authors/dfox/"&gt;baseball writing&lt;/a&gt; as well). I'm pleased to report though that on August 30 we rolled out our first deliverable based on this architecture. This deliverable helps to automate the updating of sponsor information entered on our web site and to kick certain requests to a human workflow process for resolution based on a series of business rules. &lt;br /&gt;&lt;br /&gt;The solution consists of our external web site Compassion.com, a web service with a series of web methods implemented using Microsoft's EDAF (about which more to follow) implemented in C#, MSMQ, three BizTalk Server 2004 orchestrations and two workflow processes implemented in the Ultimus BMP Suite 7.1. &lt;br /&gt;&lt;br /&gt;Since it went into production we've recorded over 35,000 service calls and the system is humming along quite well. Currently, we're in the process of making a few tweaks in order to provide a 1.1 release before moving on to our next deliverable. &lt;br /&gt;&lt;br /&gt;During this time I'll take the opportunity to continue the discussion of our &lt;a href="http://realsoa.blogspot.com/2005/05/defining-services-platform.html"&gt;Services Platform&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-112716402329548442?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/112716402329548442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=112716402329548442&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112716402329548442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/112716402329548442'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/09/real-soa.html' title='Real SOA!'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111756402454314045</id><published>2005-05-31T11:13:00.000-07:00</published><updated>2005-05-31T11:35:51.276-07:00</updated><title type='text'>Implementing Services</title><content type='html'>In my previous post I mentioned that we made a decision to use the &lt;a href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=9c29a963-594e-4e7a-9c45-576198df8058"&gt;Microsoft Development Application Framework (EDAF)&lt;/a&gt; when constructing our services in order to handle duplicate messages sent to service providers. While that is true, that's not the only reason we decided to use EDAF. I should add that we're not using EDAF for all the &lt;a href="http://realsoa.blogspot.com/2005/05/service-taxonomy.html"&gt;services in our taxonomy&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What we did decide was to implement the various types of services as follows:&lt;br /&gt;&lt;img src="http://users.adelphia.net/~danagonistes/images/servicetaxonomy.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Process Services&lt;/strong&gt;. Implemented as BizTalk 2004 orchestrations or Ultimus workflows. These services will be exposed both through a &lt;em&gt;Service Façade&lt;/em&gt; implemented as an EDAF operation (business action). A Process Service may encapsulate more than one orchestration if those orchestrations are a logical part of the process. However, if a Process Service invokes another Process Services it would do so through the Service Agent and its Service Façade. In other words logical boundaries need to be drawn between Process Services even if they are implemented as orchestrations on the same BizTalk installation.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Activity Services&lt;/strong&gt;. Where transactional coordination of the entity services is required, implemented as BizTalk orchestrations. These services will be exposed through a service façade implemented as an EDAF operation. Where transactional coordination is not required, for example in the case where a business activity can be encapsulated in a single Domain Layer stored procedure that includes the transactional control, the service can be implemented as an EDAF services&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Entity Services&lt;/strong&gt;. Implemented as EDAF services&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Infrastructure Services&lt;/strong&gt;. Implemented as EDAF services&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The way these services interact can be seen in the following diagram.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;As mentioned above, our architecture calls for the implementation of Service Facades through which services of all types will be invoked. This is one of the two primary patterns that we wanted to implement and which EDAF could really help us tackle. More formerly, these patterns are:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/architecture/soa/default.aspx?pull=/library/en-us/dnbda/html/srorientwp.asp"&gt;&lt;strong&gt;Service Façade&lt;/strong&gt;&lt;/a&gt;. This pattern implements services using a common framework to ensure consistent enforcement of a variety of operational requirements such as management, performance monitoring, security, and logging. In order to implement these cross-cutting concerns our architecture employs the Enterprise Development Application Framework (EDAF) version 1.1. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Service Agent&lt;/strong&gt;. As discussed in &lt;a href="http://realsoa.blogspot.com/2005/05/service-agent.html"&gt;my previous post&lt;/a&gt; this pattern encapsulates the concerns of service consumers with regard to service discovery, security credentials, and intelligent caching of time-sensitive data (e.g., token for a reservation message pattern). Because Compassion will primarily include clients built on the Microsoft .NET platform, the service agents will be developed as .NET class library assemblies&lt;/li&gt;&lt;/ul&gt;In the next post I'll lay out our justification for using EDAF.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111756402454314045?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111756402454314045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111756402454314045&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111756402454314045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111756402454314045'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/implementing-services.html' title='Implementing Services'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111755595166376185</id><published>2005-05-31T09:09:00.000-07:00</published><updated>2005-05-31T11:08:23.826-07:00</updated><title type='text'>Service Communication</title><content type='html'>&lt;p&gt;The next in the series of standards we published as a part of the our &lt;a href="http://realsoa.blogspot.com/2005/05/defining-services-platform.html"&gt;Services Platform&lt;/a&gt; is that of &lt;em&gt;Service Communication&lt;/em&gt;. Essentially, this set of standards encompasses the means by which services communicate and includes the following requirements: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;The ability to provide guaranteed messaging from a service consumer to a service provider &lt;/li&gt;&lt;li&gt;The ability to ensure that a service provider only processes a unique message one time, even if it is received multiple times (idempotent messaging) &lt;/li&gt;&lt;li&gt;The ability for every message to have a unique message ID in the header of the message &lt;/li&gt;&lt;li&gt;The ability to track how messages flow through the services providers to delegate (sub-contract) service providers &lt;/li&gt;&lt;li&gt;The ability for a service provider to know which service consumer called it&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In short, the way we tackled these requirements was to implement the following:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;MSMQ for guaranteed messaging, a part of which includes the WSDL extensions &lt;a href="http://realsoa.blogspot.com/2005/05/service-contract.html"&gt;I talked about previously&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The Microsoft Enterprise Development Application Framework (EDAF) to handle duplicate messages through its Duplicate Handler&lt;/li&gt;&lt;li&gt;The specification of a Compassion-specific SOAP header in combination with WS-Addressing to carry information such as the message ID, the relationship of messages to each other, and caller and callee information&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In future posts I'll explain the last two of these in more detail.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111755595166376185?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111755595166376185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111755595166376185&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111755595166376185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111755595166376185'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/service-communication.html' title='Service Communication'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111652842944130897</id><published>2005-05-19T11:33:00.000-07:00</published><updated>2005-05-20T00:31:00.136-07:00</updated><title type='text'>Service Agent</title><content type='html'>The third of the seven categories in our &lt;a href="http://realsoa.blogspot.com/2005/05/defining-services-platform.html"&gt;Services Platform&lt;/a&gt; is that of Service Agent. This pattern encapsulates the concerns of service consumers with regard to service discovery, security credentials, intelligent caching of time-sensitive data (e.g., token for a reservation message pattern), as well as invocations of the service of course.&lt;br /&gt;&lt;br /&gt;The core tenets of how we use Service Agents in our platform is encapsulated in the statements below.&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Service agents are required&lt;/strong&gt;. Every .NET service consumer Compassion develops must employ a service agent. Therefore service developers must create a Service Agent for clients to use.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Service agents are client-side assembly.&lt;/strong&gt; The Service Agent is deployed in a client-side .NET assembly other than the consuming service’s assembly &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Service agents use a common interface&lt;/strong&gt;. A service agent interface or base class is inherited by specific service agents. This enforces common behavior among service agents and allows for code reuse. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Service agents use helper classes&lt;/strong&gt;. Service Agent Helper classes are general purpose utility classes that are invoked by the service agent and provides the implementation of specific functionality. For example, the communication with the service directory to implement service discovery is encapsulated in a helper class used by our service agent base class described below. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Essentially, when an application needs to use functionality provided in an external service, our service agent manages the semantics of communicating with that particular service. For example, the business components of a retail application could use a service agent to manage communication with the credit card authorization service, and use a second service agent to handle conversations with the courier service. Service agents isolate the idiosyncrasies of calling diverse services from applications, and can provide additional services, such as basic mapping between the format of the data exposed by the service and the format your application requires. &lt;/p&gt;&lt;p&gt;To assist with this standard a talented consultant, John McPherson of Interlink, created an elegant framework for building our service agents. For example, a &lt;strong&gt;ServiceAgentBase&lt;/strong&gt; class inherits the following interface.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;code&gt;public interface IServiceAgent&lt;br /&gt;{&lt;br /&gt;XmlDocument ExecuteOperation(&lt;br /&gt;string operation,&lt;br /&gt;XmlDocument payload,&lt;br /&gt;string messageId,&lt;br /&gt;string messageStreamId,&lt;br /&gt;string processId);&lt;br /&gt;&lt;br /&gt;void ExecuteOperationNoResponse(&lt;br /&gt;string operation,&lt;br /&gt;XmlDocument payload,&lt;br /&gt;string messageId,&lt;br /&gt;string messageStreamId,&lt;br /&gt;string processId);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;string ApplicationName&lt;br /&gt;{&lt;br /&gt;get;&lt;br /&gt;set;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;string Type&lt;br /&gt;{&lt;br /&gt;get;&lt;br /&gt;set;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;string ReplyToAddress&lt;br /&gt;{&lt;br /&gt;get;&lt;br /&gt;set;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;As you can see our basic interface allows for request-response and one-way message exchange patterns through the &lt;strong&gt;ExecuteOperation&lt;/strong&gt; and &lt;strong&gt;ExecuteOperationNoResponse&lt;/strong&gt; methods. The service agent also allows for specifying the application name, communication type to use, and the address to reply to. You'll notice that these method signatures also include three ids - message, message stream, and process. These identifiers are placed into the header of the SOAP message so that our service management features are able to track how messages flow through our SOA. We've defined a standard SOAP header that I'll lay out in a future post.&lt;br /&gt;&lt;br /&gt;The &lt;strong&gt;ServiceAgentBase&lt;/strong&gt; class then exposes these methods as protected so that derived classes may use them when implementing specific methods that map to service operations. This makes the derived classes very light allowing us to implement methods that map to service operations using less than 25 lines of code. These derived service agent classes use specific schemas for request and response messages built using the XSD.exe tool that ships with the .NET Framework SDK. The schemas are originally built in BizTalk since our &lt;a href="http://realsoa.blogspot.com/2005/05/service-taxonomy.html"&gt;Process Services&lt;/a&gt; use them. We experimented with using the &lt;a href="http://www.google.com/url?sa=U&amp;start=1&amp;amp;q=http://apps.gotdotnet.com/xmltools/xsdobjgen/&amp;amp;e=10313"&gt;XSDObjGen tool&lt;/a&gt; to generate the "bind" classes but found it had several limitations when dealing with schemas with "any" elements and so we went back to XSD although it doesn't do as good a job of representing repeating elements since it doesn't use collection classes. In a future post I'll talk about our schema standards and how we plan to support extensibility.&lt;br /&gt;&lt;br /&gt;We chose not to use the same technique (namely inheriting frmo &lt;strong&gt;SoapHttpClientProtocol&lt;/strong&gt;) Visual Studio does when creating these service agents or proxies for a couple of reasons. First and foremost, our service agents allow for invoking services over several transports which include SOAP over HTTP and SOAP over MSMQ. The SoapHttpClientProtocol class obviously does not include support for MSMQ. Secondly, our service agents create and consume specific SOAP headers as mentioned previously.&lt;br /&gt;&lt;br /&gt;The ServiceAgentBase class relies on a set of helper classes to interact with the service directory such as &lt;strong&gt;UDDIServiceDirectory&lt;/strong&gt; that inherits the &lt;strong&gt;IServiceDirectory&lt;/strong&gt; interface I discussed in a previous post. The ServiceAgentBase can then read configuration information using a configuration section handler class and either load and parse the &lt;a href="http://realsoa.blogspot.com/2005/05/service-contract.html"&gt;service contract&lt;/a&gt; (WSDL 1.1) from a local path or query the &lt;a href="http://realsoa.blogspot.com/2005/05/service-discovery.html"&gt;service directory&lt;/a&gt; based on a service key (GUID) to download and parse the WSDL. The service agent relies on the WSDL to set the SOAP action and the endpoint at which to communicate with the service.&lt;br /&gt;&lt;br /&gt;The framework also supports the idea of invoking services through a generic proxy class called &lt;strong&gt;ServiceAgentProxy&lt;/strong&gt;. This class accepts payload XmlDocument objects and uses its configuration information to create and send the SOAP messages without the client having to explicitly reference assemblies that contain specific service agent classes. This functionality has been useful in two respects already. First, we use it when invoking services from inside BizTalk orchestrations. Within BizTalk we've created a generic orchestration that subscribes to messages that contain all the metadata about the call to make as well as the payload. It then uses the ServiceAgentProxy to make the call. Secondly, we're planning on using this approach to provide a way to invoke our services from ASP 3.0 code (which is a requirement in our first deliverable). Since we didn't want to use COM interop on the ASP server we created a Service Agent Broker ASP.NET site that accepts HTTP posts that contain the metadata about the call to make as well as the payload. The broker then uses ServiceAgentProxy to make the call and return the results to the ASP site using a Response.Write.&lt;br /&gt;&lt;br /&gt;While we haven't added more sophisticated features we are planning on using service agents to do client side caching of reference data as well as using it to implement more complex message exchange patterns such as asynchronous request response using the reservation pattern.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111652842944130897?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111652842944130897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111652842944130897&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111652842944130897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111652842944130897'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/service-agent.html' title='Service Agent'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111635590919598126</id><published>2005-05-17T11:21:00.000-07:00</published><updated>2005-09-19T14:52:45.830-07:00</updated><title type='text'>Service Contract</title><content type='html'>The second category of our &lt;a href="http://realsoa.blogspot.com/2005/05/defining-services-platform.html"&gt;Services Platform&lt;/a&gt; is Service Contract defined as &lt;span style="color:#000099;"&gt;"The request and (optional) response schemas for each operation exposed by a service, the security protocols, and the bindings associated with a service."&lt;/span&gt; Here we define "binding" as the combination of the transport protocol (e.g., HTTP, .NET remoting, MSMQ), the headers (WS-Security, WS-ReliableMessaging), and the encoding method (compressed binary, text, etc.). The W3C defines it as a concrete protocol and data format specification for a particular port type.&lt;br /&gt;&lt;br /&gt;In looking at what was out there to define service contracts it should come as no surprise that we landed on &lt;a href="http://www.w3.org/TR/wsdl"&gt;Web Services Description Language (WSDL) 1.1&lt;/a&gt;. The rationale of course is that WSDL descriptions can be referenced by our &lt;a href="http://realsoa.blogspot.com/2005/05/service-discovery.html"&gt;service directory&lt;/a&gt; (UDDI), and the combination of WSDL and UDDI is expected to promote the use of Web services worldwide. When we made this decision version 2.0 was in draft status. However, the .NET Framework 1.1 generates WSDL documents compatible with WSDL 1.1 and we plan on using the generated documents as starting points for our WSDL contracts.&lt;br /&gt;&lt;br /&gt;Of course, WSDL 1.1 defines only a SOAP/HTTP binding. In our architecture we also want to allow services to be invoked over MSMQ for reliability. As a result we needed to publish a WSDL extension schema we could use to add information that service consumers could use to invoke our services using MSMQ and receive responses.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace=&lt;br /&gt;"http://schemas.compassion.org/common/wsdl/2005-04-14" elementFormDefault="qualified" attributeFormDefault="unqualified" id="CIWSDL"&amp;gt;&lt;br /&gt;&amp;lt;xs:element name="requestQueue"&amp;gt;&lt;br /&gt;&amp;lt;xs:complexType&amp;gt;&lt;br /&gt;&amp;lt;xs:attribute name="location" type="xs:anyURI" use="required"/&amp;gt;&lt;br /&gt;&amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;&amp;lt;/xs:element&amp;gt;&lt;br /&gt;&amp;lt;xs:element name="responseQueue"&amp;gt;&lt;br /&gt;&amp;lt;xs:complexType&amp;gt;&lt;br /&gt;&amp;lt;xs:attribute name="location" type="xs:anyURI" use="required"/&amp;gt;&lt;br /&gt;&amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;&amp;lt;/xs:element&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;As you can see this schema includes requestQueue and responseQueue elements that are to be used in the WSDL 1.1 port element to identify the MSMQ queues through which services can be invoked and responses received.&lt;br /&gt;&lt;br /&gt;The following is an example WSDL document that uses the WSDL extension schema.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;wsdl:definitions&lt;br /&gt;xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"&lt;br /&gt;xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"&lt;br /&gt;xmlns:s="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"&lt;br /&gt;xmlns:tns="http://tempuri.org/"&lt;br /&gt;xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"&lt;br /&gt;xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"&lt;br /&gt;targetNamespace="http://tempuri.org/"&lt;br /&gt;xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"&lt;br /&gt;&lt;strong&gt;xmlns:ca="http://schemas.compassion.com/common/wsdl/2005-04-14/&lt;/strong&gt;"&amp;gt;&lt;br /&gt;&amp;lt;wsdl:types&amp;gt;&lt;br /&gt;&amp;lt;s:schema elementFormDefault="qualified"&lt;br /&gt;targetNamespace="http://tempuri.org/"&amp;gt;&lt;br /&gt;&amp;lt;s:element name="HelloWorld"&amp;gt;&lt;br /&gt;&amp;lt;s:complexType /&amp;gt;&lt;br /&gt;&amp;lt;/s:element&amp;gt;&lt;br /&gt;&amp;lt;s:element name="HelloWorldResponse"&amp;gt;&lt;br /&gt;&amp;lt;s:complexType&amp;gt;&lt;br /&gt;&amp;lt;s:sequence&amp;gt;&lt;br /&gt;&amp;lt;s:element minOccurs="0" maxOccurs="1"&lt;br /&gt;name="HelloWorldResult" type="s:string" /&amp;gt;&lt;br /&gt;&amp;lt;/s:sequence&amp;gt;&lt;br /&gt;&amp;lt;/s:complexType&amp;gt;&lt;br /&gt;&amp;lt;/s:element&amp;gt;&lt;br /&gt;&amp;lt;/s:schema&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:types&amp;gt;&lt;br /&gt;&amp;lt;wsdl:message name="HelloWorldSoapIn"&amp;gt;&lt;br /&gt;&amp;lt;wsdl:part name="parameters"&lt;br /&gt;element="tns:HelloWorld" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:message&amp;gt;&lt;br /&gt;&amp;lt;wsdl:message name="HelloWorldSoapOut"&amp;gt;&lt;br /&gt;&amp;lt;wsdl:part name="parameters"&lt;br /&gt;element="tns:HelloWorldResponse" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:message&amp;gt;&lt;br /&gt;&amp;lt;wsdl:portType name="Service1Soap"&amp;gt;&lt;br /&gt;&amp;lt;wsdl:operation name="HelloWorld"&amp;gt;&lt;br /&gt;&amp;lt;wsdl:input message="tns:HelloWorldSoapIn" /&amp;gt;&lt;br /&gt;&amp;lt;wsdl:output message="tns:HelloWorldSoapOut" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:operation&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:portType&amp;gt;&lt;br /&gt;&amp;lt;wsdl:binding name="Service1Soap"&lt;br /&gt;type="tns:Service1Soap"&amp;gt;&lt;br /&gt;&amp;lt;soap:binding&lt;br /&gt;transport=http://schemas.xmlsoap.org/soap/http&lt;br /&gt;style="document" /&amp;gt;&lt;br /&gt;&amp;lt;wsdl:operation name="HelloWorld"&amp;gt;&lt;br /&gt;&amp;lt;soap:operation&lt;br /&gt;soapAction=http://tempuri.org/HelloWorld&lt;br /&gt;style="document" /&amp;gt;&lt;br /&gt;&amp;lt;wsdl:input&amp;gt;&lt;br /&gt;&amp;lt;soap:body use="literal" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:input&amp;gt;&lt;br /&gt;&amp;lt;wsdl:output&amp;gt;&lt;br /&gt;&amp;lt;soap:body use="literal" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:output&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:operation&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:binding&amp;gt;&lt;br /&gt;&amp;lt;wsdl:binding name="Service1SoapMSMQ"&lt;br /&gt;type="tns:Service1SoapMSMQ"&amp;gt;&lt;br /&gt;&amp;lt;soap:binding&lt;br /&gt;transport=http://schemas.xmlsoap.org/soap/msmq&lt;br /&gt;style="document" /&amp;gt;&lt;br /&gt;&amp;lt;wsdl:operation name="HelloWorld"&amp;gt;&lt;br /&gt;&amp;lt;soap:operation&lt;br /&gt;soapAction="http://tempuri.org/HelloWorld"&lt;br /&gt;style="document" /&amp;gt;&lt;br /&gt;&amp;lt;wsdl:input&amp;gt;&lt;br /&gt;&amp;lt;soap:body use="literal" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:input&amp;gt;&lt;br /&gt;&amp;lt;wsdl:output&amp;gt;&lt;br /&gt;&amp;lt;soap:body use="literal" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:output&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:operation&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:binding&amp;gt;&lt;br /&gt;&amp;lt;wsdl:service name="Service1"&amp;gt;&lt;br /&gt;&amp;lt;wsdl:port name="Service1Soap"&lt;br /&gt;binding="tns:Service1Soap"&amp;gt;&lt;br /&gt;&amp;lt;soap:address&lt;br /&gt;location="http://win2k3dev/ProcessCreditCard/Service1.asmx" /&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:port&amp;gt;&lt;br /&gt;&amp;lt;wsdl:port name="Service1SoapMSMQ"&lt;br /&gt;binding="tns:Service1SoapMSMQ"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;strong&gt;&amp;lt;ci:requestQueue&lt;br /&gt;location="urn:DIRECT=OS:compassion.com\RequestQ" /&amp;gt;&lt;br /&gt;&amp;lt;ci:responseQueue&lt;br /&gt;location="urn:DIRECT=OS:compassion.com\ResponseQ" /&amp;gt;&lt;/strong&gt;&lt;br /&gt;&amp;lt;/wsdl:port&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:service&amp;gt;&lt;br /&gt;&amp;lt;/wsdl:definitions&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;Here the WSDL contract defines two ports. The first is a SOAP port that uses HTTP as the transport while the second is a SOAP port that uses MSMQ as the transport. The requestQueue and responseQueue elements are located inside the port.&lt;br /&gt;&lt;br /&gt;It should be noted that the transport is defined in the binding element located within the Service1SoapMSMQ element. By convention, and utilizing section 3.3 of the SOAP 1.1 specification (http://www.w3.org/TR/wsdl), the transport attribute is set to http://schemas.xmlsoap.org/soap/msmq to denote to a service consumer that the binding uses MSMQ as a transport.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111635590919598126?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111635590919598126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111635590919598126&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111635590919598126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111635590919598126'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/service-contract.html' title='Service Contract'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111629982716631139</id><published>2005-05-16T19:37:00.000-07:00</published><updated>2005-05-16T20:17:07.173-07:00</updated><title type='text'>Service Discovery</title><content type='html'>&lt;p&gt;The first of the &lt;a href="http://realsoa.blogspot.com/2005/05/defining-services-platform.html"&gt;seven categories&lt;/a&gt; in our "Services Platform" is Service Discovery. We defined this category as &lt;span style="color:#000099;"&gt;"The automatic identifying of a software-based service which allows processing functions to be offered and then executed after they have been located. Also includes design time notification"&lt;/span&gt;. In determining what our standard would be we developed a set of requirements and use cases to describe the desired functionality.&lt;br /&gt;&lt;br /&gt;The requirements are: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;The ability to publish services in a searchable repository (service directory). &lt;/li&gt;&lt;li&gt;The ability for a developer to view available service bindings for a service within the IDE and select one. &lt;/li&gt;&lt;li&gt;The ability for a software developer to see available service bindings for a service and select one. &lt;/li&gt;&lt;li&gt;The ability for a repository to maintain a list of subscribers. &lt;/li&gt;&lt;li&gt;The ability for a repository to send email notification to subscribers. &lt;/li&gt;&lt;li&gt;The ability for a repository to detect a breaking change to a service contract. &lt;/li&gt;&lt;li&gt;The ability for a developer to register a service as a subscriber to a particular service provider for the purposes of impact analysis. &lt;/li&gt;&lt;li&gt;The ability for a service directory to have high availability by running on multiple nodes that are network load balanced. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And the use cases are: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Publish a Service&lt;/strong&gt;. At design time, the developer publishes the new service to the service repository via a web-based user interface. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Modify a Service&lt;/strong&gt;. At design time, the developer modifies an existing service and publishes the modified service via a web-based user interface. If this is a breaking change, then this invokes the notification use case below. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Search for a Service&lt;/strong&gt;. At design time, the developer needs the ability to query a service repository to discover whether or not a specific service exists to determine whether to build a new one or employ existing one (not re-inventing the wheel). &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Select a Service Endpoint&lt;/strong&gt;. At design time, the developer needs to choose among service endpoints (e.g., MSMQ, .NET Remoting, SOAP) based on the relevant system requirements &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Service Directory Notifies Subscribers of Contract Change&lt;/strong&gt;. At design time, the service directory sends an email notification to a subscribing set of developers when an existing service contract changes. This is done for the sake of impact analysis. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Developer Subscribes to a Service&lt;/strong&gt;. At design time, the developer registers their application as a consumer of a particular service that is listed in the service directory. Registration involves providing the mailing list (Exchange Group, but preferably not an individual email address) of the developer responsible for responding to contract changes. The value that this provides is the ability for the notificaiton use case to know who the service consumers of a particular service are and how to notify them when a breaking change occurs&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Developer Un-Subscribes to a Service&lt;/strong&gt;. At design time, the developer un-registers their application as a consumer of a particular service that is listed in the service directory. This terminates the ability for notification.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Application Discovers Service at Startup&lt;/strong&gt;. At runtime during application startup, the application needs to discover initially/dynamically what channel/binding resolves to a specific endpoint and what the service contract is at that endpoint (provided by service directory). &lt;em&gt;Note&lt;/em&gt;: It is a best practice to persist (cache) in the application the service data from most recent contact with the service directory. This mitigates any issues should the Service Directory be unavailable. This will likely be implemented in a template class that is used to derive classes that need this functionality. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Application Discovers Service Change at Runtime&lt;/strong&gt;. At runtime during application execution, the application needs to be able to discover dynamically if an endpoint changes or whether a contract changes and take appropriate remedy action. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As we looked at this list we found that Universal Description, Discovery and Integration (UDDI) 2.0 as implemented on Windows Server 2003 satisfied some but not all of these requirements. Where UDDI is weak (or rather non-existant) is on the subscription and notification end. &lt;/p&gt;&lt;p&gt;After discussing the situation with Microsoft we decided that we would provisionally adopt UDDI 2.0 on Windows Server 2003 as the standard for Service Discovery and then later (after our first deliverable) add our own extensions to provide the subscription and notification services we'll need in the long term. We felt we could afford to follow this course since most clients in our architecture will interact with the directory through a Service Agent or "proxy" that is client-side. In fact, as I'll describe later, our Service Agent abstracts the calls to the directory at runtime (the last two use cases) using the interface defined below so that we can later switch directories or implement our own.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;namespace Compassion.Services.Common.Directory&lt;br /&gt;{&lt;br /&gt;  public interface IServiceDirectory&lt;br /&gt;  {&lt;br /&gt;    IServiceEndpoint RetrieveServiceEndpointUsingUuid&lt;br /&gt;      (string type, string serviceKey);&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;br /&gt;    IServiceEndpoint RetrieveServiceEndpointUsingServiceInterface&lt;br /&gt;     &lt;/code&gt;&lt;code&gt;(string type, string serviceInterface);&lt;br /&gt;&lt;br /&gt;    void SetConnection(string url, bool secure);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We've then implemented a UddiServiceDirectory class that inherits this interface and uses the Microsoft UDDI SDK to interact with the directory. You'll notice that the basics of the interface allow for retrieving the service endpoint (an object that encapsulates the communication transport) using either the service key (a GUID like that used in UDDI) or the name of the service interface. The type parameter is used to determine which service endpoint will be returned. In our first go round we've defined "Default" and "Reliable" that map to an HTTP or MSMQ end point respectively.&lt;/p&gt;&lt;p&gt;And even though the UDDI 3.0 specification is published, only UDDI 2.0 is implemented on Windows Server 2003 and so that gives us the core level of functionality (the first three requirements) out of the box that we don't need to implement. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111629982716631139?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111629982716631139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111629982716631139&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111629982716631139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111629982716631139'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/service-discovery.html' title='Service Discovery'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111598844037968408</id><published>2005-05-13T05:40:00.000-07:00</published><updated>2005-05-13T05:47:20.390-07:00</updated><title type='text'>Service Taxonomy</title><content type='html'>&lt;p&gt;As promised I will get back to the services platform we're following here at Compassion. But before doing so I wanted to discuss briefly our concept of "service taxonomy". Basically, we've defined four types of services that have different characteristics. The idea is that these different types of services may be implemented in different technologies that are suited to those characteristics. They include:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Process Services&lt;/strong&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Exposes a business process &lt;/li&gt;&lt;li&gt;Typically long running and invoked using a one-way or notification (reservation) pattern &lt;/li&gt;&lt;li&gt;Defines exceptions, escalations, and/or retries &lt;/li&gt;&lt;li&gt;Encapsulates rules particular to the business process &lt;/li&gt;&lt;li&gt;Invokes entity services to persist data and infrastructure services to perform steps in the business process &lt;/li&gt;&lt;li&gt;Includes transaction control using compensation &lt;/li&gt;&lt;li&gt;Includes rules particular to the business process &lt;/li&gt;&lt;li&gt;One process service may act as a controller for another and invoke it &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Activity Services &lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Exposes business activities that encapsulate calls to multiple entity services and perhaps infrastructure services to perform a single activity &lt;/li&gt;&lt;li&gt;Each operation scoped as a logical unit of work &lt;/li&gt;&lt;li&gt;Typically immediate request-response pattern &lt;/li&gt;&lt;li&gt;Includes rules that are common to the organization &lt;/li&gt;&lt;li&gt;Returns exceptions &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Entity Services &lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Exposes business entity and associated reference data &lt;/li&gt;&lt;li&gt;Typically immediate request-response pattern &lt;/li&gt;&lt;li&gt;Uses a published schema to represent the entity &lt;/li&gt;&lt;li&gt;Returns exceptions &lt;/li&gt;&lt;li&gt;Encapsulates data consistency rules and CRUD+ that are common to the entire organization &lt;/li&gt;&lt;li&gt;May invoke infrastructure services for data validation &lt;/li&gt;&lt;li&gt;Each operation scoped as a logical unit of work &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Infrastructure Services &lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Exposes shared functionality that is not specific to a business process or entity (not domain specific) &lt;/li&gt;&lt;li&gt;Typically immediate request-response &lt;/li&gt;&lt;li&gt;May abstract interactions with third party services or legacy systems &lt;/li&gt;&lt;li&gt;Returns exceptions &lt;/li&gt;&lt;li&gt;Does not invoke other services &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;More about how we have decided to implement each of these soon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111598844037968408?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111598844037968408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111598844037968408&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111598844037968408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111598844037968408'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/service-taxonomy.html' title='Service Taxonomy'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111523509972019233</id><published>2005-05-04T12:24:00.000-07:00</published><updated>2005-05-04T12:48:05.080-07:00</updated><title type='text'>Tenets of Service Orientation</title><content type='html'>&lt;p&gt;Before I get into the service standards it's appropriate to lay the groundwork by defining what we mean by &lt;em&gt;service-orientation&lt;/em&gt; or &lt;em&gt;service oriented architecture&lt;/em&gt;. Much of this is probably familiar to many readers and is based the lead of some key Microsoft architects, but is provided as a stake in the ground.&lt;br /&gt;&lt;br /&gt;Although definitions of this term vary in the industry the idea within Compassion an SOA or service-oriented architecture is an orchestrated sequence of messaging, transformation, routing and processing events in which XML technologies expose the message content and the components that operate on the messages.&lt;br /&gt;&lt;br /&gt;Technically a service exposes an interface &lt;em&gt;contract &lt;/em&gt;that encapsulates operations within a specific domain (business or technical for example). This contract defines the behavior (&lt;em&gt;policy&lt;/em&gt;) of the service, the &lt;em&gt;messages &lt;/em&gt;used to interact with the service, and the &lt;em&gt;message exchange patterns&lt;/em&gt; the service employs. The service manages its own state information. Because the interface contract is platform and language independent, the technology used to define messages must also be agnostic with respect to any specific platform/language. Therefore, messages are constructed using XML documents that conform to XML &lt;em&gt;schemas &lt;/em&gt;(XSD). Services then exchange messages with &lt;em&gt;applications &lt;/em&gt;or other services.&lt;br /&gt;&lt;br /&gt;In short service-orientation encompasses the following tenets: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Explicit Boundaries&lt;/strong&gt; – services are bounded by their contracts that define specific messages they accept and return&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Autonomous&lt;/strong&gt; – services are self-contained and built to last. The applications that use them will change more frequently than the services themselves &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Negotiation via policy&lt;/strong&gt; – services expose their requirements such as security and message exchange patterns via policies in the contract &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Exposed Schema and Contract&lt;/strong&gt; – service consumers use the contract and the schema it contains in order to create messages that interact with the service &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Message Driven&lt;/strong&gt; – all interaction with the service occurs through messages. Messages share schema and contract but not class or internal representation &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Reliable &lt;/strong&gt;- services are by definition shared resources and so is not the purview of a single application. In other words services are built to last, applications and business processes are built to change. As a result there is an implicit requirement that services be reliable. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Available&lt;/strong&gt; – just as in the previous tenet services must be highly available since they will be shared by a wide variety of applications&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111523509972019233?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111523509972019233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111523509972019233&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111523509972019233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111523509972019233'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/tenets-of-service-orientation.html' title='Tenets of Service Orientation'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111523374885600580</id><published>2005-05-04T11:48:00.000-07:00</published><updated>2005-05-04T12:09:08.866-07:00</updated><title type='text'>Defining a Services Platform</title><content type='html'>In my previous post I discussed the steps Compassion was taking in order to implement SOA. As promised I won't bore you with business process specifics (step number 1) but it might be of interest to many of you the SOA standards we've adopted. These were written in large part by a extremely talented fellow Compassion architect named Chuck Boudreau (and owner of Golden Hills Software and the &lt;a href="http://www.surveygold.com/"&gt;SurveyGold&lt;/a&gt; product).&lt;br /&gt;&lt;br /&gt;The way we approached this task is to define a "services platform" that includes seven key categories in which we published standards for our IT organization. These categories describe essential services necessary to enable effective communications between a service consumer and a service provider. The idea of doing so was based on advice from the book &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/B0009ESOAU/qid=1115233598/sr=1-3/ref=sr_1_3/102-9170829-0377700?v=glance&amp;s=books"&gt;Understanding SOA with Web Services&lt;/a&gt; by Newcomer and Lomow. &lt;br /&gt;&lt;br /&gt;Here they are:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Service Discovery&lt;/strong&gt;&lt;br /&gt;The automatic identifying of a software-based service which allows processing functions to be offered and then executed after they have been located. Also includes design time notification&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Service Contract&lt;/strong&gt;&lt;br /&gt;The request and (optional) response schemas for each operation exposed by a service, the security protocols, and the bindings associated with a service automatic identifying of a software-based service. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Service Agents (Proxies)&lt;/strong&gt;&lt;br /&gt;These isolate the idiosyncrasies of calling diverse services from your application, and can make available additional services, such as basic mapping between the format of the data exposed by the service and the format your application requires.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Communication&lt;/strong&gt;&lt;br /&gt;The envelope schema including addressing and context to support routing and correlation of messages sent between service consumers and service providers. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;br /&gt;Message encryption, service consumer authentication and security consumer authorization and how authorization is managed.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Message Exchange Patterns&lt;/strong&gt;&lt;br /&gt;Service contracts express valid message exchange patterns between two parties. The party that initiates communication is called the initiator. The other party is called the service. Service contracts specify one or more operation contracts. An operation contract represents an individual message exchange or a correlated request/reply message exchange&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Management/Quality&lt;/strong&gt;&lt;br /&gt;Addresses operational and management concerns including logging, performance monitoring, duplicate message handling and exception management.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the posts that follow I'll drill down into each of these and describe what is included in each standard and a little about how we arrvied at the standard.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111523374885600580?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111523374885600580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111523374885600580&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111523374885600580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111523374885600580'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/05/defining-services-platform.html' title='Defining a Services Platform'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111466844626848704</id><published>2005-04-27T23:04:00.000-07:00</published><updated>2005-04-27T23:07:26.270-07:00</updated><title type='text'>SOA Step by Step</title><content type='html'>&lt;p&gt;At &lt;a href="http://www.compassion.com"&gt;Compassion&lt;/a&gt; the decision was made to move towards service orientation in order to support an ever growing number of sponsored children. Currently, Compassion manages data on over 650,000 children who are sponsored by individuals and groups around the world. That number is likely to grow to over one million children by sometime in 2007. By constructing new systems using the principles of service orientation and introducing business process management software, the idea is to build systems composed of processes and services that can be scaled out to meet that demand.&lt;/p&gt;&lt;p&gt;The process of moving from client/server development (a monolithic Powerbuilder application performs almost all business functions today with a SQL Server backend) to service orientation is a challenging one to say the least. The general path that we’ve chosen is the following:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Identify a project (a set of business processes) where service oriented architecture can be implemented along side existing systems&lt;/li&gt;&lt;li&gt;Evaluate the SOA landscape and publish a set of SOA standards within the IT organization&lt;/li&gt;&lt;li&gt;Build a reference implementation or working model that uses the standards&lt;/li&gt;&lt;li&gt;Use the reference implementation as the template for implementing the project&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Compassion is a Microsoft shop and so the tools we’ll be using in this endeavor include Visual Studio, BizTalk, SQL Server, IIS, and MSMQ as well as a business process software product from &lt;a href="http://www.ultimus.com/index"&gt;Ultimus&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111466844626848704?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111466844626848704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111466844626848704&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111466844626848704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111466844626848704'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/04/soa-step-by-step.html' title='SOA Step by Step'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12390913.post-111430866259534216</id><published>2005-04-23T19:06:00.000-07:00</published><updated>2005-04-23T19:11:02.596-07:00</updated><title type='text'>SOA</title><content type='html'>Recently my family and I moved from Kansas City to start a new job with &lt;a href="http://www.compassion.com"&gt;Compassion International&lt;/a&gt;. As a part of this job I'm working with a great team to implement the standards, architecture, and first project in Compassion's Service Oriented Architecture (SOA) using Microsoft technology. &lt;br /&gt;&lt;br /&gt;On this blog I intend to share our experiences as we make our way down this road. Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12390913-111430866259534216?l=realsoa.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://realsoa.blogspot.com/feeds/111430866259534216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12390913&amp;postID=111430866259534216&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111430866259534216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12390913/posts/default/111430866259534216'/><link rel='alternate' type='text/html' href='http://realsoa.blogspot.com/2005/04/soa.html' title='SOA'/><author><name>Dan Agonistes</name><uri>http://www.blogger.com/profile/07863051818485888739</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
