Gobbledygooks2024-10-18T09:18:14+00:00http://richardhallgren.com/Richardrichard.hallgren@gmail.comHow to document an integration architecture2024-03-08T09:00:00+00:00http://richardhallgren.com/how-to-document-an-integration-architecture<p>One could argue that creating good documentation for an integration solution is harder than with other types of software projects. The reason is that integration solutions almost always span over many systems and services and that we often talk about <em>hundreds</em> of integrations, touching almost every part of your architecture.</p>
<p>Keeping track of such a complex system is literally <em>impossible</em> without the right documentation. š¤Æ</p>
<figure>
<img src="../assets/massive-interconnect.jpg" alt="Interconnected systems" />
<figcaption>An example of bad documentation ...</figcaption>
</figure>
<h2 id="basic-principles-of-good-documentation-for-an-integration-architecture">Basic principles of good documentation for an integration architecture</h2>
<h3 id="1-visualizations-and-diagrams-are-more-important-than-textual-documentation">1. Visualizations and diagrams are more important than textual documentation.</h3>
<p>Textual documentation has its place and is important. But when it comes to trying to describe complex scenarios, visualizations in the form of architectural diagrams are easier to quickly understand and therefore arguably the most important part of your documentation.</p>
<h3 id="2-focus-on-the-high-level-diagrams">2. Focus on the high-level diagrams.</h3>
<p>As developers, weāre good at documenting all the little technical details in our solutions. But we often document things we end up looking up in the live code and configurations. Focus on high-level documentation, the overall picture, and how the different parts of your solutions relate to each other.</p>
<h3 id="3-make-it-readable-for-everyone">3. Make it readable for everyone.</h3>
<p>UML and complex notations are great - if you understand them fully. The <a href="https://c4model.com">C4 model</a> formalized the idea of a much simpler notation, based on boxes and arrows - easier to understand and work with.</p>
<p>Use a dead simple notation that everybody can write and read.</p>
<h3 id="4-make-it-useful-for-everyone">4. Make it useful for everyone.</h3>
<p>Besides a simple notation, the <a href="https://c4model.com">C4 model</a> describes a few different diagrams with increasing levels of detail. Using different levels makes it possible to drill down from an overview into more detailed diagrams. Similar to zooming in and out of a digital map.</p>
<blockquote>
<p>Utilizing the levels and the simple notation in the C4 model, diagrams can have information useful for non-technical business users and describe large parts of architecture, without cluttering them down with too many details.</p>
</blockquote>
<h2 id="the-c4-levels-in-an-integration-context">The C4 levels in an integration context</h2>
<p>Letās look at the three levels that make up good integration documentation.</p>
<figure>
<img src="../assets/levels.png" alt="The levels of the c4-model" />
<figcaption>C4 model diagrams levels with increasing detail.</figcaption>
</figure>
<h3 id="level-1-context---the-overall-picture">Level 1 (Context) - The Overall picture</h3>
<p>For quickly understanding an integration architecture the most important part of documentation is the high-level documentation. It shows all the systems and the data-flows between them. Not the nitty-gritty details, just what systems are involved and what data is transferred between them.</p>
<p>In smaller architectures, itās possible to describe all systems and data-flows in a single level 1 diagram. In large ones, we need to choose a context to avoid too large and hard-to-read diagrams. In this example, the context is the <code class="language-plaintext highlighter-rouge">e-Commerce</code> part of the architecture.</p>
<figure>
<img src="../assets/revision-level-1.png" alt="Revision system architecture diagram at level 1" />
<figcaption>Level 1, Overall picture example - <a href="https://my.revision.app/diagram/6idZKQTeD8C9">https://my.revision.app/diagram/6idZKQTeD8C9</a>.</figcaption>
</figure>
<p>Itās important to keep these diagrams as simple as possible. Itās often tempting to include more details than necessary. Try to skip everything besides concrete systems and what type of data thatās transferred. The reason for this is that these diagrams otherwise get too complicated, hard to work with and hard to understand.</p>
<p>This part of the documentation is <em>important</em>. This is information that often is hard to understand by looking at the code and configuration.</p>
<p>This is also the part of the documentation that business users will understand. As we all know, getting the business users involved is critical for making the right decisions and in the end creating solutions that actually help the business in the right way.</p>
<p>Even though most people would agree that the overall picture is important to have documented, Iāve found that this is the part most developers tend to skip.</p>
<h3 id="level-2-container---the-integration-processes">Level 2 (Container) - The Integration Processes</h3>
<p>Itās hard to define an integration. In the overall picture product data are moved between several systems. Is the integration the part that moves the products between <code class="language-plaintext highlighter-rouge">InRiver PIM</code> and <code class="language-plaintext highlighter-rouge">Dynamics 365 PO</code>? Or is the integration the overall process that makes sure the products end up in all the destination systems?</p>
<p>Leaving that discussion aside we can agree that the purpose of an integration is to support some sort of business process. In this case, the handling of product master data.</p>
<p>Documenting how we support a business process is the second level of diagrams.</p>
<p>The difference between this and the level 1 diagram is that weāll zoom in to a specific area and that weāll here include more details - things that we didnāt want to include in the overall picture to keep it easy to understand. In the example, weāre showing that product master data actually is distributed using a product service. Weāre also including other details we didnāt show in the level 1 diagram.</p>
<figure>
<img src="../assets/revision-level-2.png" alt="Revision system architecture diagram at level 2" />
<figcaption>Level 2, Integration Process example - <a href="https://my.revision.app/diagram/bwoG8AXEhhxD">https://my.revision.app/diagram/bwoG8AXEhhxD</a>. Shows how product master data flows between systems. </figcaption>
</figure>
<p>Again this is information that is hard to get from reading code and configuration and that is important for getting the business users to understand what weāre actually building.</p>
<p>Itās important to try and keep purely technical details out of this diagram and try and focus on more business rules like information. Information that is useful for a business user.</p>
<p>Example of information we might include on level 2;</p>
<ul>
<li>whatās triggering the transfer</li>
<li>duplication checks</li>
<li>conversions</li>
<li>transformations of data, and so on</li>
</ul>
<h3 id="level-3---the-integration-details">Level 3 - The Integration Details</h3>
<p>This is probably the diagram that needs the least explanation. This is the part I often find well-documented and maintained. Here we document all the technical components and implementation details.</p>
<p>This is however also the part that doesnāt always require that much documentation. Much of the details at this level can easily be found in code and configuration and itās easy to spend time documenting things that in the end developers will look up code and configuration instead.</p>
<figure>
<img src="../assets/revision-level-3.png" alt="Revision system architecture diagram at level 3" />
<figcaption>Level 3, Integration Details example - <a href="https://my.revision.app/diagram/RmXsxDtuAEHy">https://my.revision.app/diagram/RmXsxDtuAEHy</a>. Shows a detailed view of how product master data in moved between one system to another.</figcaption>
</figure>
<h2 id="the-revision-diagramming-tool">The Revision diagramming tool</h2>
<p>The example diagrams in this post is created using <a href="https://revision.app">Revision</a>. A tool specialized to make sure your dev teams avoid wasting time on documentation no one reads.</p>
Build and generate environment specific binding files for BizTalk Server using Team Foundation Build Services2015-03-31T11:00:00+00:00http://richardhallgren.com/build-and-generate-environment-specific-binding-files-for-biztalk-server-using-team-foundation-build-services copy<p>As most know a BizTalk Solution has two major parts ā its resources in form of dlls, and its configuration in form of bindings.
In an <a href="http://richardhallgren.com/build-and-generate-msi-for-biztalk-server-using-team-foundation-build-services/">previous post</a>
I described how to build and pack <em>resources</em> into an MSI using Team Foundation Server (TFS) Build Services. Managing the configuration in a similar way is equally important.
So letās see how we can build environment specific binding files using TFS Build Services and some config transformations syntax goodness!</p>
<p><img src="https://www.dropbox.com/s/3c4hz5v643v1p4z/5.png?raw=1" alt="Workflow" /></p>
<h2 id="creating-a-simple-binding-example-for-development-and-test-environment">Creating a simple binding example for development and test environment</h2>
<p>Letās start with a simple example of a simple binding with a receive port, receive location and a
send port for two different environments - one called āTestā and one āProductionā.</p>
<table class="post" border="0" cellspacing="0" cellpadding="0">
<tr>
<th>Port type</th>
<th>Name</th>
<th>Destination path in Test</th>
<th>Destination path in Production</th>
</tr>
<tr>
<td>Receive Port</td>
<td>BtsSample_ReceivePort_A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>Receive Location</td>
<td>BtsSample_ReceivePort_A_Location (File)</td>
<td>C:\Temp\In\*.xml</td>
<td>C:\Temp\In\*.xml</td>
</tr>
<tr>
<td>Send Port</td>
<td>BtsSample_SendPort_A (File)</td>
<td>C:\Temp\<strong>TEST</strong>\Out\%MessageID%.xml</td>
<td>C:\Temp\<strong>PROD</strong>\Out\%MessageID%.xml</td>
</tr>
</table>
<p>As one can see thereās a small difference between the send ports destinations paths in Test and Production.</p>
<h2 id="exporting-a-binding-template">Exporting a binding template</h2>
<p>Next weāll create a binding template. The binding template will hold all information that is shared between the different environments.
This is achieved this by an ordinary export of the application binding from the BizTalk Administration Console - as youāve probably done many times before.
<script src="https://gist.github.com/riha/72a597136892e428cf92.js"></script></p>
<h2 id="creating-environment-specific-bindings-using-webconfig-transformation-syntax">Creating environment specific bindings using web.config Transformation Syntax</h2>
<p>The <a href="https://msdn.microsoft.com/en-us/library/dd465326.aspx">Web.config Transformation Syntax</a> is feature that showed up in Visual Studio 2010 and
is often used to transform app.config and web.config files between different versions and environments ā but it will of course work on any type
of configuration file. Including BizTalk binding files!</p>
<p>So for each environment weāll then create an environment specific config file that only contains the values that differs between the template and
the values for that environment. We use the Web.config Transformation Syntax to match the nodes and values that we like to update in the template.</p>
<p>Below is the Test environment specific file matching the send port and replacing the value with the value specific for Test.
<script src="https://gist.github.com/riha/9f9fb0d2ca57502bd6f5.js"></script></p>
<p>The Production specific file also matches the send port but with a different value for the Destination path.
<script src="https://gist.github.com/riha/bf86d3de83f48b910809.js"></script></p>
<h2 id="using-msbuild-to-execute-the-transformation">Using MSBuild to execute the transformation</h2>
<p>As part of the Visual Studio installation an MSBuild target is installed for executing the transform.
The target is installed into the standard <a href="https://msdn.microsoft.com/en-us/library/ms164309.aspx">MSBuild Extensions Path</a>
which usally mean something lilke <code class="language-plaintext highlighter-rouge">C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets</code>
depending a Visual Studio version etc.</p>
<p>Finally weāll add a small .proj file to pass some parameters to the MSBuild process. We need to tell the process what file to use as
template and what different environment specific files we like to use.
<script src="https://gist.github.com/riha/79c4dab8854b8db6c692.js"></script></p>
<p>Next we can kick of MSBuild and point it to the cretated proj file. <code class="language-plaintext highlighter-rouge">C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild build.proj</code>.</p>
<p>Voila! MSBuild has performed our transformation and created two complete environment specific binding file by combining the template with the specific environment files - one of test and one for production.</p>
<p><img src="https://www.dropbox.com/s/i0lt7i3lu54uih5/2.png?raw=1" alt="Two specific binding files" /></p>
<h2 id="generating-the-file-using-tfs-build-services">Generating the file using TFS Build Services</h2>
<p>Start by setting up a TFS build definition as described in previous post on
<a href="http://richardhallgren.com/build-and-generate-msi-for-biztalk-server-using-team-foundation-build-services/">Generating BizTalk MSI using TFS Build Services</a>.</p>
<p>We then need to add the $(DestinationPath) property to our Destination path to make sure the outputted binding files are written to the same
path as the rest of the resources.</p>
<script src="https://gist.github.com/riha/5213f920b22912fd1476.js"></script>
<p>Once we have our build template all thatās needed is to add the build.proj file to the files to compile as shown below.</p>
<p><img src="https://www.dropbox.com/s/o71ofgvt1f5ngay/3.png?raw=1" alt="Adding a build file" /></p>
<p>When finally running the build our two complete binding files are written to the deployment area and ready for installation!</p>
<p><img src="https://www.dropbox.com/s/szlteu8h963o1z7/4.png?raw=1" alt="Binding files in the deployment area" /></p>
Build and generate MSI for BizTalk Server using Team Foundation Build Services2015-02-26T11:00:00+00:00http://richardhallgren.com/build-and-generate-msi-for-biztalk-server-using-team-foundation-build-services<p>Using a build server and leveraging continuous integration is good practice in any software
development project. The idea behind automated build and continuous integrations is to have a server that
monitors oneās source code repository and builds the solution as changes occur. This separate build
activity alone will ensure that all artifacts are checked in and that a successful build doesnāt depend on any artifacts or settings on the development machines.</p>
<p><img src="https://www.dropbox.com/s/jepbxxkn38ixy3e/1.png?raw=1" alt="Build server" /></p>
<p>Today build servers do a lot more as part of the build - the build process usually involves execution of
tests, labeling the source as well as packing the solution into a deployable artifact.</p>
<p>In this post weāll see how a build process can be achieved using Team Foundation (TFS) Build Services, building a BizTalk project that results in
a deployable MSI artifact.</p>
<h2 id="tfs-build-services">TFS Build Services</h2>
<p><a href="https://msdn.microsoft.com/en-us/library/ee259687.aspx">TFS Build services</a> is a component that is part of the standard TFS install media.
Each TFS build controller controls a number of āBuild Agentsā that will perform the actual build process. For each solution to build one has to
define its process. These processes are described in a āBuild Templateā that tells the agent what steps to go through
and in what order.</p>
<p>āBuild Templatesā in TFS Build Services are defined using Visual Studio. The image below shows a build template accessed through Visual Studio Team Explorer.</p>
<p><img src="https://www.dropbox.com/s/4n5dmiepn0bmrzb/2.png?raw=1" alt="Visual Studio Team Explorer Build Templates" /></p>
<h3 id="major-steps-in-a-build-template">Major steps in a build template</h3>
<p>As one creates a new build template for a solution one has to go through the following major steps:</p>
<p><strong>1. Define a trigger</strong></p>
<p>Decides what should trigger the build. Should it be triggered manually, should it be a scheduled build or should it
be triggered at a check-in of new code?</p>
<p><strong>2. Source Setting</strong></p>
<p>This will tell the build process what part of the source tree the build template is relevant for. When queueing
a new build this is the part of the source tree that will be downloaded to the staging area. It also tells the build
services where on disk the source should be downloaded to.</p>
<p><strong>3. Process</strong></p>
<p>This is where all the steps and activities that the build service should perform are defined. Team Foundation Build
Services comes with a number of standard templates and custom ones can be added. In this post weāll however stick with the default one.</p>
<h2 id="build-your-first-biztalk-solution">Build your first BizTalk solution</h2>
<p>Building BizTalk Server solution using TFS Build Services is straight forward.</p>
<p>In this post I will use <a href="https://github.com/riha/BtsMsiTask/tree/master/Sample">this sample</a> BizTalk solution. After checking it into Team
Foundation Source Control (Iāll use TFS Source control in this post but itāll work similarly using Git) Iāll create a new build template for the solution. All thatās
needed to change is the MsBuild platform setting property, so weāre using x86 when executing MsBuild as shown below.</p>
<p><img src="https://www.dropbox.com/s/lgcnk72pqko72s2/3.png?raw=1" alt="Build process and the MsBuild platform setting property" /></p>
<p>After queuing a build we can in the TFS Build Explorer see a successful build!</p>
<p><img src="https://www.dropbox.com/s/u5lpl4hw7h7jxjx/4.png?raw=1" alt="Successful build in TFS Build Explorer" /></p>
<p>We can also download the output from the build where we can see all our build artifacts!
<img src="https://www.dropbox.com/s/erx3twhocbelfyq/5.png?raw=1" alt="First artifact drop" /></p>
<h2 id="using-btsmsitask-to-create-a-msi-as-part-of-the-build">Using BtsMsiTask to create a MSI as part of the build</h2>
<p>So far so good, but we started the article by saying that what we wanted was a deployable artifact. In the case of
BizTalk this means a BizTalk MSI. Letās see what we need to change to also have the build process create a MSI.</p>
<p><strong>1. Install BtsMsiTask</strong></p>
<p>Download and install <a href="http://richardhallgren.com/BtsMsiTask/">BtsMsiTask</a>. This will install a MsBuild task for generating the MSI.</p>
<p><strong>2. Add a MsBuild project file</strong></p>
<p>Add a MsBuild project file (<code class="language-plaintext highlighter-rouge">build.proj</code>) to the solution</p>
<script src="https://gist.github.com/riha/24856902e68bae4ec244.js"></script>
<p>The project file will tell the BtsMsiTask process what artifacts to include.
Add the created project file to the solution and check it in as part of the solution.</p>
<p><strong>3. Add the MsBuild project file to the TFS build template</strong></p>
<p>Add the created MsBuild project file to the TFS build template by adding it to the list of projects to build.</p>
<p><img src="https://www.dropbox.com/s/6avtnovpdkzo0ll/6.png?raw=1" alt="Adding the build file to the build process" /></p>
<p>After another successful build we can see that we also created a MSI as part of the build!
<img src="https://www.dropbox.com/s/qtbd8pp552x9y6p/7.png?raw=1" alt="Successful build with msi" /></p>
<h2 id="adding-build-information-to-the-msi">Adding build information to the MSI</h2>
<h3 id="file-name">File name</h3>
<p>As we can see the MSI we just created ended up with the default BtsMsiFile name that is a combination of the BizTalk application name property and the
current date and time. Wouldnāt it be nice of we instead could the build number as part of the name?
BtsMsiTask has an <a href="http://richardhallgren.com/BtsMsiTask/available-parameters/">optional property</a> called <code class="language-plaintext highlighter-rouge">FileName</code> that we for
example can set to <code class="language-plaintext highlighter-rouge"><FileName>$(TF_BUILD_BUILDNUMBER).msi</FileName></code></p>
<h3 id="source-location">Source location</h3>
<p>When installing the artifact to BizTalk Server we can see that the source location property in the BizTalk Administration Console is set to
where the artifact was built on the staging area.
<img src="https://www.dropbox.com/s/8c7usslwvijnj75/8.png?raw=1" alt="Source Location without build number" /></p>
<p>Itād be nice to also have information about what build that produced these artifacts. This will give the required information to know exactly what builds that are used for all the installed artifacts.</p>
<p>We can change what is set in the source location by using the <code class="language-plaintext highlighter-rouge">SourceLocation</code> property of BtsMsiTask <code class="language-plaintext highlighter-rouge"><SourceLocation>c:\$(TF_BUILD_BUILDNUMBER)</SourceLocation></code></p>
<p>So after setting the property as below, queue another build, reinstall using the MSI and weāll get the following result with the build number in the source location property.
<img src="https://www.dropbox.com/s/fkjxfdyqyp7vf86/9.png?raw=1" alt="Source Location with build number" /></p>
<p>And finally this is the MsBuild project file we ended up with in our example. <script src="https://gist.github.com/riha/dd8d7b4a1fed1bad3ca5.js"></script></p>
Calling an on premise Microsoft Dynamics CRM using BizTalk and Active Directory Federated Security (ADFS)2014-10-17T11:00:00+00:00http://richardhallgren.com/calling-an-on-premise-microsoft-dynamics-crm-using-biztalk-and-active-directory-federated-security-(ADFS)<p>Federated security is a great way of accomplishing single-sign-on (SSO) security for your applications. Itās also a technique that is becoming increasingly relevant as things move to the cloud and weāre starting to get more hybrid situation with some applications on premise and some in the cloud.</p>
<p>Active Directory Federated Security (ADFS) is an implementation of federated security and is used by a number of Microsoft Applications, Microsoft Dynamics CRM being one of them.</p>
<p>Windows Communication Foundation (WCF) has a few techniques to simplify federated security communication and this post will show an example of using Microsoft BizTalk Server and WCF to communicate with an ADFS secured CRM installation.</p>
<h2 id="what-is-federated-security">What is federated security?</h2>
<p>Federated security at its core is pretty simple. In our scenario BizTalk Server (client) wants to login in and authenticate itself with the CRM system.</p>
<p>Traditionally the CRM system then had to manage the credentials for the client and verify these as login happened. There a number of drawback to this, the main one being that it doesnāt scale that well when weāre getting many separated systems that need access to each other as login information and login logic is spreads out across a number of systems.</p>
<p>When using federated security each part instead chooses to trust a common part (in this case the ADFS and AD), and as long as someone provide a token that can be validated with the trusted part, the CRM system will trust that it already has been authenticated and that everything is ok.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677004/35ce5cea-55e2-11e4-8283-91f8158ffbb2.png" alt="Data flow" /></p>
<ol>
<li>Authentication and requesting token</li>
<li>Authentication against AD</li>
<li>Login authenticated</li>
<li>ADFS token response</li>
<li>ADFS token based authentication</li>
<li>Response from CRM</li>
</ol>
<p>So basically a federated security model allows for separating all authentication and authorization out to a separate system.</p>
<p>As mentioned ADFS is just an implementation of federated security were Active Directory acts as the main repository with a Security Token Service implementation on top of it.</p>
<h2 id="biztalk-and-adfs">BizTalk and ADFS</h2>
<p>As BizTalk has great WCF support we can use the WCF stack to handle all of communication with ADFS and CRM. But it does involve a fair bit of configuration. BizTalk and Visual Studio will help in most mainstream WCF scenario where one can point Visual Studio at the WSDL location and a basic binding file is generated for us. However, in the case of and ADFS based WSDL this will just result in an empty binding file that doesnāt help much.</p>
<p>Lots of projects Iāve seen makes the decision at this point to use custom code and create a facade to solve authentication. As Microsoft Dynamics CRM comes with a nice SDK including a C# library to handle authentication is easy to understand how one would end up using that. The problem is however that this creates another code base that again needs to be maintained over time. One could also argue that using custom code that is called by BizTalk further complicates the overall solution and makes it harder to maintain.</p>
<p>So letās configure the authentication from scratch using Windows Communication Foundation.</p>
<h2 id="choosing-the-right-wcf-binding">Choosing the right WCF binding</h2>
<p>First thing to do is to choose the right WCF binding. Letās create a WCF-Custom Static Solicit-Response send port and choose the <code class="language-plaintext highlighter-rouge">ws2007FederationHttpBinding</code>.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4851310/55ef1c46-6071-11e4-95ad-fce44c84cf5a.png" alt="Choose binding" /></p>
<h2 id="adding-the-issuer">Adding the Issuer</h2>
<p>First thing we need to add is information on how to connect to the Issuer. The Issuer is the one issuing the ticket, in our case thatās the ADFS.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677021/615e582e-55e2-11e4-8a20-d412647a9a54.png" alt="Issuer details" /></p>
<p>First we need to add information about the address of the Issuer. The WSDL tells us that the mex endpoint for the ADFS server is located at <code class="language-plaintext highlighter-rouge">https://adfs20.xxx.yy/adfs/trust/mex</code>.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677037/75a339c6-55e2-11e4-8bee-262b54497e53.png" alt="Mex file" /></p>
<p>Browsing the WSDL for the ADFS server shows a number of different endpoints. Which one to use depends on what kind of authentication being used when requesting the token. In our case weāre using a simple username and password so weāre using the <code class="language-plaintext highlighter-rouge">usernamemixed</code> endpoint (<code class="language-plaintext highlighter-rouge">https://adfs20.xxx.yy/adfs/services/trust/2005/usernamemixed</code>).</p>
<p>Secondly we need to add information about the binding and the binding configuration for communication with the ADFS service.</p>
<p>What this basically means is that we need to add information to a second, or an inner, binding configuration. The BizTalk Server WCF configuration GUI doesnāt provide a way to set this so the only way is to configure this is to use one of the relevant configuration files (āmachine.configā or the BizTalk config) and ad a binding manually.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><bindings>
<ws2007HttpBinding>
<clear/>
<binding name="stsBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None"/>
<message clientCredentialType="UserName" establishSecurityContext="false"/>
</security>
</binding>
</ws2007HttpBinding>
</bindings>
</code></pre></div></div>
<p>Once this is setup we can point our BizTalk Server WCF configuration to the correct URL and reference the WCF inner binding we just configured.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677048/8771fe58-55e2-11e4-9fb8-cdaea394039a.png" alt="Issuer configured" /></p>
<p>Finally we need to provide the username and password to authenticate ourselves to the ADFS server.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677053/980b0d04-55e2-11e4-97d4-2c3a9befb553.png" alt="Login details" /></p>
<p>We now have communication setup to the ADFS service and should be able to get a valid ticket that we then can use to authenticate ourselves to the CRM system!</p>
<p>We now however also need to provide information on how to connect to the actual CRM system.</p>
<h2 id="configure-communication-to-crm">Configure communication to CRM</h2>
<p>The rest is easy. Letās start with adding the URL to the end service we want to call. As with any other service call weāll also add the SOAP Action Header that in this case is the Update service (<code class="language-plaintext highlighter-rouge">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Update</code>) of the <code class="language-plaintext highlighter-rouge">OrganizationService</code> service.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677061/a975aab8-55e2-11e4-9727-1ffbd12e5132.png" alt="Service details" /></p>
<p>As out service also uses SSL for encryption we need to tell the binding to use <code class="language-plaintext highlighter-rouge">TransportWithMessageCredentials</code>.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677066/bab52f7e-55e2-11e4-8c17-5c93dde94637.png" alt="Transport encryption" /></p>
<h2 id="establishing-a-security-context--or-not">Establishing a Security Context ā or not</h2>
<p>Finally there is a little tweak that is needed. WCF supports establishing a Security Context. This will cache the token and avoid asking the STS for a new token for each call to the CRM system. BizTalk Server however doesnāt seem to support this so we need to turn it off.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4677070/cc96a416-55e2-11e4-942a-851427e242ea.png" alt="Security Context" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>Understanding federated security is important and will become increasingly important as we move over to systems hosted in the cloud ā federated security is the de facto authentication standard used by hosted systems in the cloud. Avoiding custom code and custom facades is a key factor in building maintainable large scale BizTalk based systems over time. BizTalk has great WCF support and taking full advantage of it is important to be able to build solutions that easy to oversee and possible to maintain not just by those familiar and comfortable in custom code.</p>
Getting digital certificates right in BizTalk using a third party root certificate in combination with client certificate security and WCF BasicHttp2014-08-28T22:00:00+00:00http://richardhallgren.com/getting-digital-certificates-right-in-biztalk-using-a-third-party-root-certificate-and-wcf-basichttp<p>Digital certificates and asymmetric security is notoriously hard to get right in a Windows environment. Getting it right in a <em>BizTalk context</em> isnāt exactly easier.</p>
<p>In this scenario a BizTalk Server act as a client and communicates with a service over https. The service also uses a client certificate for client authentication.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4082243/e3123c2e-2eef-11e4-9218-3ec8b31c041e.png" alt="Flow" /></p>
<h2 id="long-story-short">Long story short</h2>
<p>Third party root certificates always needs to be places under āThird-Party Root Certification Authoritiesā or directly under the āTrusted Root Certification Authoritiesā folder on Local Machine level in Windows. When however also configuring the āWCF-BasicHttpā adapter to also use client certificate authorization the BizTalk Administration console requires the thumbprint id of a specific server certificate (in addition to the client certificate thumbprint). This makes the runtime also look for the for the public certificates under āTrusted Peopleā folder and <strong>causes an error if we donāt <em>also</em> place it that folder.</strong></p>
<p>In the end this requires us to add the public root certificate in two different places.</p>
<h2 id="server-certificate">Server certificate</h2>
<p>Letās start by getting the server certificate right.</p>
<p>After configuring everything in BizTalk using a standard <code class="language-plaintext highlighter-rouge">WCF-BasicHttp</code> port and selecting <code class="language-plaintext highlighter-rouge">Transport</code> security I encountered the following error message.</p>
<blockquote>
<p>A message sent to adapter āWCF-BasicHttpā on send port āSP1ā with URI āhttps://skattjakt.cloudapp.net/Service1.svcā is suspended.</p>
</blockquote>
<blockquote>
<p>Error details: System.ServiceModel.Security.SecurityNegotiationException: Could not establish trust relationship for the SSL/TLS secure channel with authority āskattjakt.cloudapp.netā. ā> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ā> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.</p>
</blockquote>
<p>The error message is pretty straightforward: <code class="language-plaintext highlighter-rouge">Could not establish trust relationship for the SSL/TLS secure channel with authority</code>.</p>
<p>The first thing that happens when trying to establish SSL channel is that a public server certificate is sent down the client for the client to use when encrypting further messages to the server. This certificate is validated so it hasnāt been revoked, that itās <code class="language-plaintext highlighter-rouge">Valid to</code> date hasnāt passed, that the <code class="language-plaintext highlighter-rouge">Issued to</code> name actually matches the services domain and so on.</p>
<p>But to be able to trust the information in the certificate it needs to be issued by someone we trust, a certificate authority (CA).</p>
<p>If we take an example of a request to Google we actually donāt trust the information in the Google server certificate, neither do we trust the intermediate certificate they use to sign their public server certificate. The root certificate that issued the intermediary Google Certificate is however one of the preinstalled trusted certificate authorities in Windows.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4075616/ca0ada30-2eb1-11e4-86fa-a00a89d34559.png" alt="Google" /></p>
<p>What authorities and certificates to trust is in Windows based on what certificates exists in the Certificate Store under the <code class="language-plaintext highlighter-rouge">Trusted Root Certificate Authorities</code> folder.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4075860/ce641792-2eb4-11e4-8544-6a20e92ea9fe.png" alt="ca" /></p>
<p>In our case the service didnāt use a certificate from one of the trusted authorities but had based their certificate on a root certificate they created themselves.</p>
<p><img src="https://cloud.githubusercontent.com/assets/1317734/4075933/8178a456-2eb5-11e4-8818-ca1b74fc66e2.png" alt="ca2" /></p>
<p>Further the Certificate Manager in Windows has three different levels: āLocal Machineā, āServiceā and āCurrent Userā. The top level is the āLocal Machineā and certificates added on this level are available for all users. āServiceā and āCurrent Userā are more specific and only available for specific services and users. From a BizTalk perspective itās important to place the certificate so itās <em>accessible for the user running the BizTalk host instance</em>.</p>
<p>So after requesting the used root certificate and placing it in the trusted authorities folder for the Local Machine weāre able to successfully establish an SSL session!</p>
<h2 id="client-certificate">Client certificate</h2>
<p>As the server however required a client certificate for authorization I reconfigured the send port to use <code class="language-plaintext highlighter-rouge">Certificate</code> as client credential type. <br />
<img src="https://cloud.githubusercontent.com/assets/1317734/4076354/713ca4c6-2eb9-11e4-8293-ed462b550fdc.png" alt="3" /></p>
<p>The BizTalk Administration Console then requires one to enter the thumbprint of the private client certificate to use. When browsing for picking the client certificate the console will look for certificates to choose from in the āPersonalā folder on the āCurrent Userā level. So for the certificate to show up one has to add the client certificate to the āPersonalā folder running as the user that eventually will hit the browse button in the console. Adding it only to the āPersonalā folder of āLocal Machineā will not make it show up in the console. As the āCurrent Userā level also is separate for each user itās very important to add it to the āPersonalā folder for the user that eventually will run the BizTalk process as this user otherwise wonāt find the certificate at runtime. In this case just pasting the thumbprint id from the certificate will work fine.</p>
<p>When selecting <code class="language-plaintext highlighter-rouge">Certificate</code> client credential type the BizTalk Administration console also requires one to pick what public server certificate to use - even though we still just want to use the same root certificate as just added to the trusted store on machine level ..? When locating server certificates to display the console will look in the āOther Peopleā folder on āLocal Computerā level. So for making our root certificate show up in the console we also have to this to this folder. It turns however out that when having a pinpointed specific server certificate <strong>the BizTalk runtime will throw an error if the server certificate is not placed in the āOther Peopleā folder</strong>. Likewise will an error we be <strong>thrown if the certificate is placed only in one of the trusted authorities folders</strong>.</p>
<blockquote>
<p>A message sent to adapter āWCF-BasicHttpā on send port āSP1ā with URI āhttps://skattjakt.cloudapp.net:444/Service42.svcā is suspended.
Error details: System.InvalidOperationException: Cannot find the X.509 certificate using the following search criteria: StoreName āAddressBookā, StoreLocation āLocalMachineā, FindType āFindByThumbprintā, FindValue ā70A9899E6CF89B014E6195ADE6E1BA12BEA58728ā.</p>
</blockquote>
<p>So in this case we need to add the public CA certificate in two different places for the communication to work.</p>
<p>Frankly I donāt see the point of having to point out a server certificate at all in this case - all I want is to configure what client certificate to use for authorization and the runtime to validate the server certificate against all CA I have in the trusted folders.</p>
Why full NuGet support for BizTalk projects is important!2014-06-03T09:33:09+00:00http://richardhallgren.com/why-full-nuget-support-for-biztalk-projects-is-important<p>Letās start with a summary for those who donāt feel like reading the full post.</p>
<p>Using NuGet to handle BizTalk dependencies for shared schemas, pipeline components and so on works fine today.</p>
<p>As .btproj files however arenāt supported by NuGet (as shown in <a href="https://nuget.codeplex.com/SourceControl/network/forks/robinhultman/NuGetWithBizTalkProjectExtension/changeset/d1f1a29c9b322670c820f52d769422cb111253b3">this pull request</a>) and are not in the current white list of allowed project types <em>Package Restore will not work</em> (issue closed as by design <a href="https://nuget.codeplex.com/workitem/3010">here</a>).</p>
<p>Not having Package Restore of course is a problem as one now is forced to check in all packages as part of the solutions, something that in the end leads to bloated and messy solutions.</p>
<p>So please reach out to your Microsoft contacts and letās get this fixed!</p>
<h3 id="nuget">NuGet</h3>
<p>As most people know NuGet is the package management solution from Microsoft for .NET. It started off as an initiative to further boost open source within the .NET community and NuGet packages uploaded to the <a href="http://www.nuget.org/">NuGet.org platform</a> are open and available directly within Visual Studio through the NuGet add-in. Currently there are well over 20 000 open packages for everyone to download and use.</p>
<p>Lately there has however been lots of discussions within the community to use NuGet as a package manager for <em>internal</em> shared resources as well (by <a href="http://www.hanselman.com/blog/NuGetForTheEnterpriseNuGetInAContinuousIntegrationAutomatedBuildSystem.aspx">Hanselman</a> and <a href="https://www.simple-talk.com/dotnet/.net-framework/taking-nuget-to-the-enterprise/">others</a>). Solutions like <a href="https://www.myget.org/">MyGet</a> allows for <em>private</em> NuGet feeds ā only available to those within your organization but still levering all the ease and control offered by NuGet.</p>
<p>Using NuGet for references has a number of of advantages:</p>
<ul>
<li>
<p><strong>Communication</strong> <br />
All available resources are directly visible in Visual Studio and when updates to a used library is a available a notification is shown. No more spam mails about changes and never read list of available libraries.</p>
</li>
<li>
<p><strong>Versioning</strong> <br />
A NuGet package has itās own versioning. This is useful as it isnāt always optimal to change the dll version, but by using the NuGet package version one can still indicate that something has changed. <br />
As you also reference a specific version of a NuGet package from your solution you always have full control of <em>exactly</em> what version youāre targeting and where to find the built and ready bits.</p>
</li>
<li>
<p><strong>Efficiency</strong> <br />
When starting to work on a project with many references one first have to get the source code from source control for the references, build these (hopefully in the right version ā¦ hopefully you have your tags and labels in order ā¦) until all the broken references are fix. <br />
With NuGet references this just works straight away and you can be sure you get the right version as the resource isnāt the latest from source control but the actual built dlls thatās part of the referenced NuGet package.</p>
</li>
</ul>
<h4 id="nuget-feeds">NuGet Feeds</h4>
<p>As mentioned NuGet feeds can be public or private. A NuGet feed is basically a RSS feed with available resources and versions of these. A feed and a NuGet server can be a hosted web based solution or something as simple as a folder where you write your NuGet packages to. The <a href="http://docs.nuget.org/docs/creating-packages/hosting-your-own-nuget-feeds">NuGet documentation</a> covers these options in depth. <br />
The point being that creating your own private NuGet feed is very simple!</p>
<blockquote>
<p>So if you havenāt already realized it by now - NuGet is not only a great tool to manage all public external dependencies but can add a <strong>a lot a value for internal references</strong> as well.</p>
</blockquote>
<h4 id="couple-of-relevant-nuget-features">Couple of relevant NuGet features</h4>
<ul>
<li>
<p><strong>NuGet Package Restore</strong> <br />
<a href="http://docs.nuget.org/docs/reference/package-restore">NuGet Package Restore</a> enables NuGet to download the used referenced package from the package area. The goal is to avoid having to check in the actual references in source control as this will bloat the version control system and in the end the create a messy solution.</p>
</li>
<li>
<p><strong>NuGet Specification (nuspec) metadata token replacements</strong> <br />
All packages are based on a nuspec file that dictates the version, package description and other meta information. <br />
NuGet has the capability to by using replacement tokens (such as <em>$version$</em> for example) read some of this information from the <em>AssemblyInfo</em> files. <br />
This is far from a critical feature but nice to have and avoid having to repeat oneself and have the same information in a number of places.**</p>
</li>
</ul>
<h3 id="biztalk-and-nuget">BizTalk and NuGet?</h3>
<p>A typical BizTalk solution has a number of shared resources such as shared schemas, shared libraries and pipeline components. As the resources usually are shared between a number of project they often live in a separate development cycle. So when opening a BizTalk project with such resources itās not only a lot of work getting the referenced code and building the references, thereās also this nagging feeling that it _might not be in the right version _and that the source might have changed since the first time the reference was added.</p>
<p>Another reference issue occurs when using a build server for a solution with references. As the solution has a dependency to the referenced project one has to make sure not only that the main solution is fetched to the build workarea by the build server, but also that all the referenced project are fetched from version control ā and again, hopefully the latest version in the attended version ā¦ <br />
This kind of works using TFS Build Service and common TFS Source Control. If however oneās using Git and have resources in separate repositories this becomes impossible as TFS Build Service currently only supports fetching a single repository per build definition to the build workarea ā¦ <br />
(This issue does not apply for <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> that has a number of different options for dependency management)</p>
<p>All the these issues are actually solved when using NuGet references instead of traditional references as we can be sure weāre getting the packaged dlls as part of the NuGet package <em>in the version that one referenced and not the latest checked in version</em>. <br />
A NuGet reference also makes things a bit easier when it comes to managing the workarea for the TFS Build Service as one only have to sure the NuGet package is available (either as checked in as part of the solution or by using Package Restore).</p>
<p><strong><em>But ā¦</em></strong></p>
<h3 id="nuget-doesnt-support-biztalk-projects">NuGet doesnāt support BizTalk projects!</h3>
<p>As disused <a href="https://nuget.codeplex.com/workitem/3010">here</a> NuGet currently doesnāt support .btproj files. As BizTalk project files are are basically a standard .NET project file with some extra information a two line change in the NuGet whitelist is needed as in <a href="https://nuget.codeplex.com/SourceControl/network/forks/robinhultman/NuGetWithBizTalkProjectExtension/contribution/5960#!/tab/changes">this pull request</a>.</p>
<p><img src="../assets/2014/06/nolove.png" alt="nolove" /></p>
<p>So the main issue it that by <em>not having full support of .btproj files Package Restore wonāt work</em> and weāre for now force to check in all the NuGet packages as part of our solutions. <br />
An other minor issue is that the token replacement feature also doesnāt work. I also think that if we could actually get full BizTalk support weād see more BizTalk specific open shared packages for things like useful libraries and pipeline components.</p>
<p><strong><em>Call for action</em></strong>: Reach out to <a href="https://twitter.com/nuget">the NuGet Team</a> or other Microsoft connections and letās get those two lines added to the white list!</p>
Talking Application Lifecycle Management and BizTalk in Gothenburg2014-02-22T14:13:29+00:00http://richardhallgren.com/presenting-on-application-lifecycle-management-and-biztalk-again<p><a href="http://www.eventbrite.com/e/biztalk-alm-tickets-10211239091?aff=eorg">Back in February</a> I and my college Robin did an presentation on ALM and BizTalk for the BizTalk User Group in Stockholm. In the two hour presentation we talked about things like:</p>
<ul>
<li>
<p>Pros and cons on distributed version control handling systems and BizTalk (more specially Git).</p>
</li>
<li>
<p>Identifying the right level of automated test ā what are the differences between integration and unit tests and how and what should one use when in a BizTalk context.</p>
</li>
<li>
<p>Using NuGet and BizTalk to handle dependencies and packages. How can we use the NuGet infrastructure to handle all BizTalk dependencies and also distribute artifacts like pipeline components within our company and teams?</p>
</li>
<li>
<p>How, in our opinion, are Continuous Integration and Delivery best handled when developing with BizTalk. In the presentation weāre looking at everything from build servers to how to handle BizTalk automated builds and packing with minimal amount of work.</p>
</li>
</ul>
<p>So, now we doing <a href="http://www.eventbrite.com/e/biztalk-alm-goteborg-tickets-10693092327?aff=eorg">the presentation all over again</a> for the newly started BizTalk User Group in Gothenburg the 24 of Mars. The presentation will be in Swedish and packed with demos.</p>
<p>Hope to see you there!</p>
Export BizTalk Server MSI packages directly from Visual Studio using BtsMsiTask2014-01-14T10:42:25+00:00http://richardhallgren.com/export-biztalk-server-msi-packages-directly-from-visual-studio-using-btsmsitask<p><em>Getting a full Continuous Integration (CI) process working with BizTalk Server is hard!</em></p>
<p><em>One of the big advantages in a working CI process is to always have tested and verified artifacts from the build server to deploy into test and production. Packaging these build resources into a deployable unit is however notorious hard in BizTalk Server as a Visual Studio build will not provide a deployable artifact (only raw dlls). The only way to get a deployable MSI package for BizTalk Server is to first install everything into the server and then export ā until now.</em></p>
<h2 id="why-continuous-integration">Why Continuous Integration?</h2>
<p><a href="http://martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a> is a concept first described by Martin Fowler back in 2006. At its core its about team communication and fast feedback but also often leads to better quality software and more efficient processes.</p>
<p><img src="../assets/2014/01/CI1.png" alt="CI" /></p>
<p>A CI process usually works something like the above picture.</p>
<ol>
<li>
<p>A developer checks in code to the source control server.</p>
</li>
<li>
<p>The build server detects that a check in has occurred, gets all the new code and initiates a new build while also running all the relevant unit tests.</p>
</li>
<li>
<p>The result from the build and the tests are sent back to the team of developers and provides them with a up to date view of the āhealthā in the project.</p>
</li>
<li>
<p>If the build and all the test are successful the built and tested resources are written to a deploy area.</p>
</li>
</ol>
<p>As one can see the CI build server acts as another developer on the team but always builds everything on a fresh machine and bases everything on what is actually checked in to source control ā guaranteeing that nothing is build using artifacts that for some reasons is not in source control or that some special setting etc is required to achieve a successful build.</p>
<p>In step 4 above the CI server also writes everything to a deploy area. A golden rule for a CI workflow is to use artifacts and packages from this area for further deployment to test and production environments ā and <em>never</em> directly build and move artifacts from developer machines! <br />
As all resources from each successful build is stored safely and labeled one automatically achieves versioning and the possibility to roll back to previous versions and packages if needed.</p>
<h2 id="what-is-the-problem-with-ci-and-biztalk">What is the problem with CI and BizTalk?</h2>
<p>It is important to have the build and feedback process as efficient as possible to enable frequent checkins and to catch possible errors and mistake directly. As mentioned it is equally as important that the resources are written to the deploy area are the ones used to deploy to test and production so one gets all the advantages with versioning and roll back possibilities etc.</p>
<p>The problem with BizTalk Server is however that only building a project in Visual Studio does not gives us a deployable package (only raw dlls)!</p>
<p>There are a number of different ways to get around this. One popular option is to automate the whole installation of the dlls generated in the build. This not only requires a whole lot of scripting and work, it also requires a full BizTalk Server installation on the build server. The automated process of installation also takes time and slows down the feedback loop back to development team. There are however great frameworks as for example the <a href="http://biztalkdeployment.codeplex.com/">BizTalk Deployment Framework</a> to help with this (this solution of course also enables integration testing using <a href="http://bizunit.codeplex.com/">BizUnit</a> and other framework).</p>
<p>Some people would also argue that the whole script package and the raw dlls could be moved onto test and production and viewed on as a deployment package. But MSI is a powerful packaging tool and BizTalk Server has a number of specialized features around MSI. As MSI also is so simple and flexible it usually the preferred solution by IT operations.</p>
<p>A final possibility is of course to directly add the resources one by one using BizTalk Server Administration console. In more complex solutions this however takes time and requires deeper knowledge into the solution as one manually has to know in what order the different resources should be added.</p>
<h2 id="another-option-in-btsmsitask">Another option in BtsMsiTask</h2>
<p>Another option is then to use <a href="https://github.com/riha/BtsMsiTask">BtsMsiTask</a> to directly generate a BizTalk Server MSI from the Visual Studio build and MsBuild.</p>
<p><img src="../assets/2014/01/SimplerProcess1.png" alt="SimplerProcess" /></p>
<p>The BtsMsiTask uses same approach and tools as the MSI export process implemented into BizTalk Server but extracts it into a MSBuild task that can be directly executed as part of the build process.</p>
<p>BtsMsiTask enables the CI server to generate a deployable MSI package directly from the Visual Studio based build <em>without</em> having to first install into BizTalk Server!</p>
Presenting on āEfficient system integration documentationā at BizTalk User Group Sweden2012-10-14T20:02:45+00:00http://richardhallgren.com/presenting-on-efficient-system-integration-documentation-at-biztalk-user-group-sweden<p>Iāve talked a lot about efficient documentation previously on this blog, both when in comes to splitting the documentation up in different layers as <a href="http://www.richardhallgren.com/using-biztalk-config-explorer-as-a-new-way-of-documenting-your-biztalk-solutions/">here</a>, but also in relation to tools BizTalk Documenter and <a href="http://btswebdoc.com/">BizTalk Web Documenter</a> for automatically generation technical documentation as <a href="http://www.richardhallgren.com/reborn-as-biztalk-web-documenter/">here</a>.</p>
<p>Last week I however had the pleasure to present on the BizTalk User Group Sweden meeting and got to talk all documentation for a whole hour! You can find the PPT from the meeting <a href="http://biztalkusergroup.se/blogs/info/BUGS%20docs%20-%20Richard%20Hallgren.pptx">here</a>.</p>
<p>I ended the presentation by presenting the ten commandments for efficient system integration documentation:</p>
<p><img style="float: right;margin-top:20px;" src="http://drbristol.files.wordpress.com/2010/10/10-commandments.gif" /></p>
<p><strong>I.</strong> Thou shall <em>not</em> manually document anything that can be automatized!</p>
<p><strong>II.</strong> Thou shall keep it <em>simple</em> & make it <em>look nice</em></p>
<p><strong>III.</strong> Thou shall <em>use a wiki</em> based platform</p>
<p><strong>IV.</strong> Thou shall <em>use pictures</em> whenever appropriate</p>
<p><strong>V.</strong> Thou shall have <em>well defined guidelines</em> for your documentation</p>
<p><strong>VI.</strong> Thou shall have a <em>well defined target audience</em> for your documentation</p>
<p><strong>VII.</strong> Thou shall <em>document continuously</em> in your project</p>
<p><strong>VIII.</strong> Thou shall have a <em>common vocabulary</em> and common icons defined</p>
<p><strong>IX.</strong>Thou shall <em>test your documentation</em> with target audience</p>
<p><strong>X.</strong> Thou as the <em>developer</em> of an integration should <em>document it</em></p>
Reborn as BizTalk Web Documenter!2012-09-30T20:27:40+00:00http://richardhallgren.com/reborn-as-biztalk-web-documenter<p>About a year ago <a href="http://www.richardhallgren.com/using-biztalk-config-explorer-as-a-new-way-of-documenting-your-biztalk-solutions/">I published a project</a> that helps automating documentation for BizTalk Server ā much like <a href="http://biztalk2010autodc.codeplex.com/">BizTalk Documenter</a> but with the difference that this tools instead generates a dynamic web site. Iāve called in Config Explorer, a name I knew was sh*t from the start but the best I could come up with at the time.</p>
<p>After a while however, when enough people told me that they also thought the name was crap I decided to change it to <a href="http://btswebdoc.com/">BizTalk Web Documenter</a>. Iāve also moved the whole <a href="https://github.com/riha/btswebdoc">project to GitHub</a>.</p>
<p>Iāll try and spend a bit more time on the project than I have the last year and will update the <a href="http://btswebdoc.com/">documentation</a>, wiki and roadmap as well as implement a few new features.</p>
<p>I hope youāll help me ā fork the project today!</p>
Using BizTalk Web Documenter as a new way of documenting your BizTalk solutions2011-09-02T11:01:22+00:00http://richardhallgren.com/using-biztalk-config-explorer-as-a-new-way-of-documenting-your-biztalk-solutions<blockquote>
<p>2012-09-30: Iāve renamed the whole project and moved it to <a href="https://github.com/riha/btswebdoc">GitHub</a>. Hope to see you there!</p>
</blockquote>
<p>As most BizTalk developers/architects you have probably been in a situation were documentation of your integration solution has been discussed. And you probably also been just as happy as me when you first found <a href="http://biztalkdocumenter.codeplex.com/">BizTalk Documenter</a>. BizTalk Documenter is a great tool for extracting all that configuration data that is so vital to BizTalk and create a nice technical documentation of it.</p>
<p><img src="../assets/2011/09/documentation-levels.png" alt="documentation levels" />There are of course several levels to documentation in BizTalk Server based solution were the technical information is at the lowest level. Above that you would then have you integration process descriptions and then possible another level above that where you fit the integration processes into bigger business processes, and so on ā but letās stick to the technical documentation for now.</p>
<p>BizTalk Documenter does a nice job of automating the creation of technical documentation, instead of basically having to all that configuration job a second time when documenting. Doing technical documentation by hand usually also breaks down after a while as solution setup and configuration changes a lot and the work is really time consuming. And as documentation that isnāt up to date frankly is completely worthless people soon looses interest in both reading and maintaining the technical documentation.</p>
<p>Using BizTalk Documenter however has a few problems ā¦</p>
<ul>
<li>
<p>The tool generates either a <a href="http://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help">CHM</a> file or a word file with documentation. As more and more organizations however move their documentation online new output formats are needed.</p>
</li>
<li>
<p>The latest 3.4 versions of the tools throws OutOfMemory Exceptions on bigger solutions.</p>
</li>
</ul>
<h3 id="biztalk-config-explorer-web-documenter">BizTalk <strike>Config Explorer</strike> Web Documenter</h3>
<p>As we started trying to find ways to solve the issues above we had a few ideas we wanted the new solution to handle better.</p>
<ul>
<li>
<p><strong>Web based documentation</strong><br />
A web based documentation is both much easier to distribute and more accessible to read ā sending a link and reading a web page rather then sending around a CHM file.</p>
</li>
<li>
<p><strong>Easy way of see changes in versions</strong><br />
Sometimes one wants to see how things have changed and how things used to be configured. The tools should support ājumping back in timeā and see previous versions.</p>
</li>
</ul>
<p><a href="http://demo.configexplorer.com/"><img src="../assets/2011/09/config-explorer.png" alt="config explorer" /></a></p>
<p>Check out an an <a href="http://btswebdoc.com/demo">example</a> of a Config Explorer yourself.</p>
<h3 id="getting-started">Getting started</h3>
<p>Config Explorer is a open source tool <a href="https://github.com/riha/btswebdoc">published</a> on <strike>CodePlex GitHub</strike> - a good place to start to understanding the workflow of creating documentation and to download the tool itself.</p>
<h3 id="contribute">Contribute!</h3>
<p>This release is a 1.0 release and there will are many features we havenāt had time for, but a few of them weāve planned for future releases. Unfortunately there will however also be bugs and obvious things weāve missed. Please use the <strike>CodePlex GutHub</strike> <a href="https://github.com/riha/btswebdoc/issues">Issue Tracker</a> to let us know what you like us to add and what possible issues youāve found.</p>
<p>Iāll of course also check for any comments here! <a href="../assets/2011/09/wlEmoticon-winkingsmile.png">Winking smile</a></p>
Update to BAM Service Generator2011-06-03T05:58:29+00:00http://richardhallgren.com/update-to-bam-service-generator<p>I have previously <a href="http://www.richardhallgren.com/end-to-end-tracking-using-bam-services-and-the-bam-service-generator-tool/">written</a> about how to generate a types set of WCF services to achieve end-to-end BAM based tracking ā making BAM logging possible from outside potential firewalls and/or from non .NET based clients.</p>
<p>In that post I reference a open source tool to generate the services based on the BAM definition files to be able to make types BAM API calls. I called the tool <a href="http://bmsrvgen.codeplex.com/">BAM Service Generator</a> and itās published on CodePlex.</p>
<p>The first version of the tool only made it possible to make simple activity tracking calls, even missing the option to defining a custom activity id. All advanced scenarios like continuation, activity and data reference or even updating a activity wasnāt possible. That has now been fixed and the second version of the tool enables the following operations.</p>
<ul>
<li>
<p><strong>LogCompleteActivity</strong> <br />
Creates a simple logging line and is the most efficient option if one only wantās to begin, update and and end an activity logging as soon as possible.</p>
</li>
<li>
<p><strong>BeginActivity</strong> <br />
Start a new activity with a custom activity id</p>
</li>
<li>
<p><strong>UpdateActivity</strong> <br />
Updates a already started activity and accepts a types object as a parameter. The typed object is of course based on whatās has been defined in the BAM definition file. Multiple updates can be made until EndActivity is called.</p>
</li>
<li>
<p><strong>EnableContinuation</strong> <br />
Enables continuation. This is used if you have multiple activity loggings that belong together but you can not use the same activity id. This enables you to tie those related activities together using some other set of id (could for example be the invoice id).</p>
</li>
<li>
<p><strong>AddActivivityReference</strong> <br />
Add a reference to an another activity and enables you to for example display a link or read that whole activity when reading the main one.</p>
</li>
<li>
<p><strong>AddReference</strong> <br />
Adds a custom reference to something that isnāt necessarily an activity. Could for example be a link to a document of some sort. Limited to 1024 characters.</p>
</li>
<li>
<p><strong>AddLongReference</strong> <br />
Similar to AddReference but enables to also store a blog of data using the LongRefernceData parameter ā limited to 512 KB.</p>
</li>
<li>
<p><strong>EndActivity</strong> <br />
Ends a started activity.</p>
</li>
</ul>
<p>Let <a href="mailto:richard.hallgren@gmail.com">me know</a> if you think that something is missing, if something isnāt working as would expect etc.</p>
End-to-end tracking using BAM services and the BAM Service Generator tool2011-01-18T14:48:36+00:00http://richardhallgren.com/end-to-end-tracking-using-bam-services-and-the-bam-service-generator-tool<p>An integration between systems can often be view upon as a chain of system and services working together to move a message to its final destination.</p>
<p><a href="../assets/2011/01/image5.png"><img src="../assets/2011/01/image_thumb5.png" alt="image" /></a></p>
<p>One problem with this loosely-coupled way of dealing with message transfers is that its hard to see if and where something has gone wrong. Usually all we know is that the sending system has send the message, but the final system never received it. The problem could then be within any of the components in between. Tracking messages within BizTalk is one thing but achieving a _end-to-end tracking _within the whole āchainā is much harder.</p>
<p>One way of solving the end-to-end tracking problem is to use <a href="http://msdn.microsoft.com/en-us/library/ee253368(BTS.10).aspx">BAM</a>. BAM is optimized for these kind of scenarios were we might have to deal with huge amount of messages and data ā several of the potential problems around these issues are solved out-of-the-box (write optimized tables, partitioning of tables, aggregated views, archiving jobs and so on).</p>
<p>And even though BAM is a product that in theory isnāt tied to BizTalk its still a product that is easier to use in the context of BizTalk than outside of it due tools like the <a href="http://msdn.microsoft.com/en-us/library/ee253776(v=bts.10).aspx">BizTalk Tracking Profile Editor</a> and the built in BAM-interceptor patterns within BizTalk. It is however fully possible to track BAM data and take advantage of the BAM infrastructure even outside of BizTalk using the <a href="http://msdn.microsoft.com/en-us/library/ee277263(v=bts.10).aspx">BAM API</a>.</p>
<p>The BAM API is a .NET based API used for writing tracking data to the BAM infrastructure from any .NET based application. There are however a few issues with this approach.</p>
<p>The application sending the tracking data has to be .NET based and use the loose string based API. So for example writing to the āApprovedInvoiceā activity below would look something like this ā lots of untyped strings.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public void Log(ApprovedInvoicesServiceType value)
{
string approvedInvoicesServiceActivityID = Guid.NewGuid().ToString();
var es = new DirectEventStream("Integrated Security=SSPI;Data Source=.;Initial Catalog=BAMPrimaryImportw", 1);
es.BeginActivity("ApprovedInvoices", approvedInvoicesServiceActivityID);
es.UpdateActivity("ApprovedInvoices", approvedInvoicesServiceActivityID,
"ApprovedDate", "2011-01-18 12:02",
"ApprovedBy", "Richard",
"Amount", 122.34,
"InvoiceId", "Invoic123");
es.EndActivity("ApprovedInvoices", approvedInvoicesServiceActivityID);
}
</code></pre></div></div>
<p>One way of getting around problem with the usage of strings is to use the ā<a href="http://generatetypedbamapi.codeplex.com/">Generate Typed BAM API tool</a>ā. The tool reads the BAM definition file and generates a dll containing strong types that corresponds to the fields in the definition. By referencing the dll in the sending application we can get a strong typed .NET call. The fact that this still however <em>requires a .NET based application</em> remains.</p>
<p>The obvious way to solve the limitation of a .NET based client - and to get one step closer to a end-to-end tracking scenario - is of course to wrap the call to the API in a service.</p>
<h3 id="bam-service-generator">BAM Service Generator</h3>
<p><a href="http://bmsrvgen.codeplex.com/">BAM Service Generator</a> is very similar to the Generate Typed BAM API tool mentioned above with the difference that instead of generation a .NET dll it generates a WCF service for each activity.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>c:\Tools\bmsrvgen.exe /help
BAM Service Generator Version 1.0
Generates a WCF service based on a BizTalk BAM definition file.
-defintionfile: Sets path to BAM definition file.
-output: Sets path to output folder.
-namespace: Sets namespace to use.
Example: bmsrvgen.exe -defintionfile:c:\MyFiles\MyActivityDef.xml
-output:c:\tempservices -nampespace:MyCompanyNamespace
</code></pre></div></div>
<p>The <a href="http://bmsrvgen.codeplex.com/">BAM Service Generator</a> is a command line tool that will read the BAM definition file and generate a compiled .NET 4.0 WCF service. The service is configured with a default basicHttp endpoint and is ready to go straight into AppFabric or similar hosting.</p>
<p><a href="../assets/2011/01/image7.png"><img src="../assets/2011/01/image_thumb7.png" alt="image" /></a></p>
<p>This service-approach makes it possible to take advantage of the BAM infrastructure from all different types of system, and even in cases when they arenāt behind the same firewall! As shown in figure below this could take us one step closer to the end-to-end tracking scenario.</p>
<p><a href="../assets/2011/01/image8.png"><img src="../assets/2011/01/image_thumb8.png" alt="image" /></a></p>
<p>āBAM Service Generatorā is open-source and can be found <a href="http://bmsrvgen.codeplex.com/">here</a>.</p>
Promote properties in a EDI schema using the EDI Disassembler2010-04-23T07:08:46+00:00http://richardhallgren.com/promote-properties-in-a-edi-schema-using-the-edi-disassembler<p>Iāve doing a lot of EDI related work in BizTalk lately and I have to say that Iāve really enjoyed it! EDI takes a while to get used to (see example below), but once one started to understand it Iāve found it to be a real nice, strict standard - with some cool features built into BizTalk!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>UNB+IATB:1+6XPPC+LHPPC+940101:0950+1'
UNH+1+PAORES:93:1:IA'
MSG+1:45'
IFT+3+XYZCOMPANY AVAILABILITY'
ERC+A7V:1:AMD'
IFT+3+NO MORE FLIGHTS'
ODI'
TVL+240493:1000::1220+FRA+JFK+DL+400+C'
...
</code></pre></div></div>
<p>There are however some things that _doesnāt _work as expected ā¦</p>
<h3 id="promoting-values">Promoting values</h3>
<p>According to the <a href="http://msdn.microsoft.com/en-us/library/bb226404(BTS.20).aspx">MSDN documentation</a> the EDI Disassembler by default promotes the following EDI fields: UNB2.1, UNB2.3, UNB3.1, UNB11; UNG1, UNG2.1, UNG3.1; UNH2.1, UNH2.2, UNH2.3.</p>
<p>There are however situation where one would like <em>other</em> values promoted.</p>
<p>I my case I wanted the C002/1001 value in the <a href="http://www.stylusstudio.com/edifact/d04b/BGM_.htm">BGM segment</a>. This is a value identifying the purpose of the document and I needed to route the incoming message based on the value.</p>
<p>The short version is that <em>creating a property schema, promoting the field in the schema and having the EDI Disassembler promoting the value <strong>will not work</strong> (as with the XML Disassembler)</em>. To do this youāll need to use a custom pipeline component to promote the value. Rikard Alard seem to have come to the same conclusion <a href="http://rikardalard.wordpress.com/2009/06/15/promoted-properties-in-edi-schema-is-not-promoted-by-edireceive/">here</a>.</p>
<h3 id="promote-pipeline-component-to-use">Promote pipeline component to use</h3>
<p>If you donāt want to spend time on writing your own pipeline component to do this yourself you can find a nice āpromote componentā on CodePlex <a href="http://eebiztalkpipelinecom.codeplex.com/">here</a> by <a href="http://blog.eliasen.dk">Jan Eliasen</a>.</p>
<p>If you however expect to receive lots and lots of big messages you might want to look into changing the component to use XPathReader and custom stream implementations in the Microsoft.BizTalk.Streaming.dll. You can find more detailed information on how to do that in this <a href="http://msdn.microsoft.com/en-us/library/ee377071(BTS.10).aspx">MSDN article</a>.</p>
Use code blocks to extend your BizTalk custom XSLT maps2010-04-12T07:38:47+00:00http://richardhallgren.com/use-code-blocks-to-extend-your-biztalk-custom-xslt-maps<blockquote>
<p>Update 2010-04-13: Grant Samuels commented and made me aware of the fact that inline scripts might in some cases cause memory leaks. He has some further information <a href="http://linderalex.blogspot.com/2008/06/memory-leak-using-biztalk-mapper.html">here</a> and youāll find a kb-article <a href="http://support.microsoft.com/kb/918643">here</a>.</p>
</blockquote>
<p>Iāve posted a few times before on how powerful I think it is in complex mapping to be able to replace the BizTalk Mapper with a custom XSLT script (<a href="http://msdn.microsoft.com/en-us/library/aa560154(BTS.20).aspx">hereās how to</a>). The BizTalk Mapper is nice and productive in simpler scenarios but in my experience it break down in more complex ones and maintaining a good overview is <em>hard</em>. Iām however looking forward to the new version of the <a href="http://www.microsoft.com/biztalk/en/us/roadmap.aspx#2009r2">tool in BizTalk 2010</a> ā but until then Iām using custom XSLT when things gets complicated.</p>
<p>Custom XSLT however lacks a few things once has gotten used to have - such as scripting blocks, clever functoids etc. In some previously post (<a href="http://www.richardhallgren.com/how-the-extend-a-custom-xslt-in-biztalk-using-exslt-and-the-mvpxml-project/">here</a> and <a href="http://www.richardhallgren.com/using-xslt-1-0-to-summarize-a-node-set-with-comma-separated-values/">here</a>) Iāve talked about using EXSLT as a way to extend the capabilities of custom XSLT when used in BizTalk.</p>
<h3 id="bye-bye-external-libraries--heeeello-inline-scripts-">Bye, bye external libraries ā heeeello inline scripts ;)</h3>
<p>Another way to achieve much of the same functionality even easier is to use embedded scripting thatās supported by the XslTransform class. Using a script block in XSLT is easy and is also the way the BizTalk Mapper makes it possible to include C# snippets right into your maps.</p>
<p>Have a look at the following XSLT sample:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:code="http://richardhallgren.com/Sample/XsltCode"
exclude-result-prefixes="msxsl code"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<Test>
<UniqueNumber>
<xsl:value-of select="code:GetUniqueId()" />
</UniqueNumber>
<SpecialDateFormat>
<xsl:value-of select="code:GetInternationalDateFormat('11/16/2003')" />
</SpecialDateFormat>
<IncludesBizTalk>
<xsl:value-of select="code:IncludesSpecialWord('This is a text with BizTalk in it', 'BizTalk')" />
</IncludesBizTalk>
</Test>
</xsl:template>
<msxsl:script language="CSharp" implements-prefix="code">
//Gets a unique id based on a guid
public string GetUniqueId()
{
return Guid.NewGuid().ToString();
}
//Formats US based dates to standard international
public string GetInternationalDateFormat(String date)
{
return DateTime.Parse(date, new System.Globalization.CultureInfo("en-US")).ToString("yyyy-MM-dd");
}
//Use regular expression to look for a pattern in a string
public bool IncludesSpecialWord(String s, String pattern)
{
Regex rx = new Regex(pattern);
return rx.Match(s).Success;
}
</msxsl:script>
</xsl:stylesheet>
</code></pre></div></div>
<p>All one has to do is to define a code block, reference the xml-namespace used and start coding! Say goodbye to all those external library dlls!</p>
<p>Itās possible to use a few core namespaces without the full .NET namespace path but all namespaces are available as long as they are fully qualified. MSDN has a great page with all the details <a href="http://msdn.microsoft.com/en-us/library/533texsx(VS.71).aspx">here</a>.</p>
Is there a bug in BizTalk 2006 R2 SP1?2010-03-17T11:14:25+00:00http://richardhallgren.com/is-there-a-bug-in-biztalk-2006-r2-sp1<blockquote>
<p>Update 2012-03-28: This bug was fixed in the CU2 update for BizTalk 2006 R2 SP 1. Further details can be found <a href="http://support.microsoft.com/kb/2211420">here</a> and <a href="http://support.microsoft.com/kb/983185">here</a>.</p>
</blockquote>
<blockquote>
<p>Update 2010-04-12: Seems like there is a patch coming that should fix all the bugs in SP1 ā¦ Iāve been told it should be public within a week or two. Iāll make sure to update the post as I know more. Our problem is still unsolved.</p>
</blockquote>
<p>Late Thursday night last week we decided to upgrade one of our largest BizTalk 2006 R2 environment to recently released <a href="http://msdn.microsoft.com/en-us/library/ee532481(BTS.20).aspx">Service Pack 1</a>. The installation went fine and everything looked good.</p>
<p>ā¦ But after a while we started see loads of error messages looking like below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Unable to cast COM object of type 'System.__ComObject' to interface type
'Microsoft.BizTalk.PipelineOM.IInterceptor'. This operation failed because the
QueryInterface call on the COM component for the interface with IID
'{24394515-91A3-4CF7-96A6-0891C6FB1360}' failed due to the following error: Interface not
registered (Exception from HRESULT: 0x80040155).
</code></pre></div></div>
<p>After lots of investigation we found out that we got the errors on ports with the follow criteria:</p>
<ul>
<li>
<p><strong>Send port</strong></p>
</li>
<li>
<p><strong>Uses the SQL Server adapter</strong></p>
</li>
<li>
<p><strong>Has a mapping on the port</strong></p>
</li>
<li>
<p><strong>Has a BAM tracking profile associated with the port</strong></p>
</li>
</ul>
<p>In our environment the tracking on the port is on āSendDateTimeā from the āMessaging Property Schemaā. We havenāt looked further into if just any BAM tracking associated with port causes the error or if only has to do with some specific properties.</p>
<h3 id="reproduce-it-to-prove-it">Reproduce it to prove it!</h3>
<p>Iāve setup a really simple sample solution to reproduce the problem. <a href="http://www.richardhallgren.com/blogfiles/SP1Issue.zip"><strong>Download it here</strong></a>.</p>
<p>The sample receives a XML file, maps it on the send port to schema made to match the store procedure. It also uses a dead simple tracking definition and profile to track a milestone on the send port.<a href="../assets/2010/03/image.png"><img src="../assets/2010/03/image_thumb.png" alt="image" /></a></p>
<h4 id="sample-solution-installation-instructions">Sample solution installation instructions</h4>
<ol>
<li>
<p>Create a database called āTestā</p>
</li>
<li>
<p>Run the two SQL scripts (āTBL_CreateIds.sqlā and āSP_CreateAddID.sqlā) in the solution to create the necessary table and store procedure</p>
</li>
<li>
<p>Deploy the BizTalk solution just using simple deploy from Visual Studio</p>
</li>
<li>
<p>Apply the binding file (āBinding.xmlā) found in the solution</p>
</li>
<li>
<p>Run the BM.exe tool to deploy the BAM tracking defintion. <br />
Should look something like:</p>
<p>bm.exe deploy-all -definitionfile:<the path="" to="" the="" solution="">\BAM\SimpleTestTrackingDefinition.xml</the></p>
</li>
<li>
<p>Start the tracking Profile editor and open the āSimpleTestTrackingProfile.bttā that youāll find in the solution and apply the profile</p>
</li>
<li>
<p>Drop the test file in the receive folder (āInSchema_output.xmlā)</p>
</li>
</ol>
<p>The sample solution <em>fails on a environment with SP 1 but works just fine on a ācleanā BizTalk 2006 R2 environment</em>.</p>
<h3 id="what-about-you">What about you?</h3>
<p>I havenāt had time to test this on a BizTalk 2009 environment but Iāll update the post as soon as I get around to it.</p>
<p>We also currently have a support case with Microsoft on this and Iāll make sure to let you as soon as something comes out of that. But until then Iād be <strong>_really grateful _</strong>to hear from you if any of you have the same behavior in your BizTalk 2006 R2 SP1 environment.</p>
Using XSLT 1.0 to summarize a node-set with comma separated values2010-02-26T09:31:50+00:00http://richardhallgren.com/using-xslt-1-0-to-summarize-a-node-set-with-comma-separated-values<p>Pure XSLT is very powerful but it definitely has its weaknesses (Iāve written about how to extend XSLT using mapping and BizTalk previously <a href="http://www.richardhallgren.com/how-the-extend-a-custom-xslt-in-biztalk-using-exslt-and-the-mvpxml-project/">here</a>) ā¦ One of those are handling numbers that uses a different decimal-separator than a point (ā.ā).</p>
<p>Take for example the XML below</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><Prices>
<Price>10,1</Price>
<Price>10,2</Price>
<Price>10,3</Price>
</Prices>
</code></pre></div></div>
<p>Just using the <a href="http://www.zvon.org/xxl/XSLTreference/Output/function_sum.html">XSLT sum-function</a> on these values will give us a āNaNā values. To solve it weāll have to use recursion and something like in the sample below.</p>
<p>The sample will select the node-set to summarize and send it to the āSummarizePriceā template. It will then add the value for the first Price tag of the by transforming the comma to a point. It will then check if itās the last value and if not use recursion to call into itself again with the next value. It willĀ keep adding to the total amount until it reaches the last value of the node set.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><xsl:template match="Prices">
<xsl:call-template name="SummurizePrice">
<xsl:with-param name="nodes" select="Price" />
</xsl:call-template>
</xsl:template>
<xsl:template name="SummurizePrice">
<xsl:param name="index" select="1" />
<xsl:param name="nodes" />
<xsl:param name="totalPrice" select="0" />
<xsl:variable name="currentPrice" select="translate($nodes[$index], ',', '.')"/>
<xsl:choose>
<xsl:when test="$index=count($nodes)">
<xsl:value-of select="$totalPrice + $currentPrice"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="SummurizePrice">
<xsl:with-param name="index" select="$index + 1" />
<xsl:with-param name="totalPrice" select="$totalPrice + $currentPrice" />
<xsl:with-param name="nodes" select="$nodes" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</code></pre></div></div>
<p>Simple but a bit messy and nice to have for future cut and paste ;)</p>
Streaming pipeline and using context ResourceTracker to avoid disposed streams2010-02-22T08:50:16+00:00http://richardhallgren.com/streaming-pipeline-and-using-resourcetracker-to-avoid-disposed-objects<p>Recently thereās been a few really good resources on streaming pipeline handling published. You can find some of the <a href="http://msdn.microsoft.com/en-us/library/ee377071(BTS.10).aspx">here</a> and <a href="http://msdn.microsoft.com/en-us/library/ff384124(BTS.10).aspx">here</a>.</p>
<p>The <a href="http://msdn.microsoft.com/en-us/library/ee377071(BTS.10,classic).aspx">Optimizing Pipeline Performance</a> MSDN article has two great examples of how to use some of the <a href="http://technet.microsoft.com/en-us/library/microsoft.biztalk.streaming(BTS.20).aspx">Microsoft.BizTalk.Streaming.dl</a> classes. The execute method of first example looks something like below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public IBaseMessage Execute(IPipelineContext context, IBaseMessage message)
{
try
{
...
IBaseMessageContext messageContext = message.Context;
if (string.IsNullOrEmpty(xPath) && string.IsNullOrEmpty(propertyValue))
{
throw new ArgumentException(...);
}
IBaseMessagePart bodyPart = message.BodyPart;
Stream inboundStream = bodyPart.GetOriginalDataStream();
VirtualStream virtualStream = new VirtualStream(bufferSize, thresholdSize);
ReadOnlySeekableStream readOnlySeekableStream = new ReadOnlySeekableStream(inboundStream, virtualStream, bufferSize);
XmlTextReader xmlTextReader = new XmlTextReader(readOnlySeekableStream);
XPathCollection xPathCollection = new XPathCollection();
XPathReader xPathReader = new XPathReader(xmlTextReader, xPathCollection);
xPathCollection.Add(xPath);
bool ok = false;
while (xPathReader.ReadUntilMatch())
{
if (xPathReader.Match(0) && !ok)
{
propertyValue = xPathReader.ReadString();
messageContext.Promote(propertyName, propertyNamespace, propertyValue);
ok = true;
}
}
readOnlySeekableStream.Position = 0;
bodyPart.Data = readOnlySeekableStream;
}
catch (Exception ex)
{
if (message != null)
{
message.SetErrorInfo(ex);
}
...
throw ex;
}
return message;
}
</code></pre></div></div>
<p>We used this example as a base when developing something very similar in a recent project. At first every thing worked fine but after a while we stared getting an error saying:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Cannot access a disposed object. Object name: DataReader
</code></pre></div></div>
<p>It took us a while to figure out the real problem here, everything worked fine when sending in simple messages but as soon as we used to code in a pipeline were we also <a href="http://geekswithblogs.net/benny/archive/2007/02/15/106329.aspx">debatched</a> messages we got the ādisposed objectā problem.</p>
<p><a href="../assets/2010/02/image1.png"><img src="../assets/2010/02/image_thumb1.png" alt="image" /></a>It turns out that when we debatched messages the execute method of the custom pipeline ran multiple times, one time for each sub-messages. This forced the .NET Garbage Collector to run.</p>
<p>The GC found the XmlTextReader that we used to read the stream as unreferenced and decided to destoy it.</p>
<p>The problem is that <strong>will also dispose the readOnlySeekable-Stream stream that we connected to our message data object</strong>!</p>
<p><strong>Itās then the BizTalk End Point Manager (EPM) that throws the error as it hits a disposed stream object when trying to read the message body and save it to the BizTalkMsgBox!</strong></p>
<h3 id="resourcetracker-to-the-rescue">ResourceTracker to the rescue!</h3>
<p>Turns out that the BizTalk message context object has a nice little class connected to it called the <em>ResourceTracker</em>. This object has a āAddResouceā-method that makes it possible to add an object and the context will the hold a reference to this object, <strong>this will tell the GC not to dispose it!</strong></p>
<p>So when adding the below before ending the method everything works fine - even when debatching messages!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>context.ResourceTracker.AddResource(xmlTextReader);
</code></pre></div></div>
Checking if BizTalk binding file is up-to date during deployment2009-12-11T10:19:52+00:00http://richardhallgren.com/checking-if-biztalk-binding-file-is-up-to-date-during-deployment<p>As all of you know the number one time consuming task in BizTalk is deployment. How many times have you worked your way through the steps below (and even more interesting - how much time have you spent on them ā¦)</p>
<ul>
<li>
<p>Build</p>
</li>
<li>
<p>Create application</p>
</li>
<li>
<p>Deploy schemas</p>
</li>
<li>
<p>Deploy transformations</p>
</li>
<li>
<p>Deploy orchestration</p>
</li>
<li>
<p>Deploy components</p>
</li>
<li>
<p>Deploy pipelines</p>
</li>
<li>
<p>Deploy web services</p>
</li>
<li>
<p>Create the external databases</p>
</li>
<li>
<p>Change config settings</p>
</li>
<li>
<p>GAC libraries</p>
</li>
<li>
<p>Apply bindings on applications</p>
</li>
<li>
<p>Bounce the host instances</p>
</li>
<li>
<p>Send test messages</p>
</li>
<li>
<p>Etc, etc ā¦</p>
</li>
</ul>
<p>Not only is this time consuming itās also <em>drop dead boring</em> and therefore also very prone - small mistakes that takes ages to find and fix.</p>
<p>The good news is however that the steps are quite easy to script. We use a combination of a couple of different open-source MsBuild libraries (like <a href="http://www.codeplex.com/sdctasks">this</a> and <a href="http://msbuildtasks.tigris.org/">this</a>) and have created our own little build framework. There is however the <a href="http://biztalkdeployment.codeplex.com/">BizTalk Deployment Framework</a> by <a href="http://www.traceofthought.net/">Scott Colescott</a> and <a href="http://www.tfabraham.com/blog/">Thomas F. Abraham</a> that looks great and is very similar to what we have (ok, ok, itās a <em>bit</em> more polished ā¦).</p>
<h3 id="binding-files-problem">Binding files problem</h3>
<p>Keeping the binding files in a source control system is of course a super-important part of the whole build concept. If something goes wrong and you need to roll back, or even rebuild the whole solution, having the right version of the binding file is critical.</p>
<p>A problem is however that <em>if someone has done changes to the configuration via the administration console and <strong>missed</strong> to export these binding to source control weāll deploy an old version of the binding when redeploying</em>. This can be a huge problem when for example addresses etc have changed on ports and we redeploy old configurations.</p>
<blockquote>
<p>What!? If fixed that configuration issue in production last week and now it back ā¦</p>
</blockquote>
<p>So <strong>how can we reassure</strong> that the binding file is up-to-date when deploying?</p>
<p>One solution is to do and export of the current binding file and compare that to one weāre about to deploy in a āpre-deployā-step using a custom MsBuild target.</p>
<h3 id="custom-build-task">Custom build task</h3>
<p>Custom build task in MsBuild are easy, a good explanation of how to write one can be found <a href="http://msdn.microsoft.com/en-us/library/t9883dzc.aspx">here</a>. The custom task below does the following.</p>
<ol>
<li>
<p>Require a path to the binding file being deployed.</p>
</li>
<li>
<p>Require a path to the old deployed binding file to compare against.</p>
</li>
<li>
<p>Using a regular expression to strip out the time stamp in the files as this is the time the file was exported and that will otherwise differ between the files.</p>
</li>
<li>
<p>Compare the content of the files and return a boolean saying if they are equal or not.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> public class CompareBindingFiles : Task
{
string _bindingFileToInstallPath;
string _bindingFileDeployedPath;
bool _value = false;
[Required]
public string BindingFileToInstallPath
{
get { return _bindingFileToInstallPath; }
set { _bindingFileToInstallPath = value; }
}
[Required]
public string BindingFileDeployedPath
{
get { return _bindingFileDeployedPath; }
set { _bindingFileDeployedPath = value; }
}
[Output]
public bool Value
{
get { return _value; }
set { _value = value; }
}
public override bool Execute()
{
_value = GetStrippedXmlContent(_bindingFileDeployedPath).Equals(GetStrippedXmlContent(_bindingFileToInstallPath));
return true; //successful
}
private string GetStrippedXmlContent(string path)
{
StreamReader reader = new StreamReader(path);
string content = reader.ReadToEnd();
Regex pattern = new Regex("<Timestamp>.*</Timestamp>");
return pattern.Replace(content, string.Empty);
}
}
</code></pre></div> </div>
</li>
</ol>
<h3 id="using-the-build-task-in-msbuild">Using the build task in MsBuild</h3>
<p>After compiling the task above when have to reference the dll in <UsingTask> element like below.</UsingTask></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><UsingTask AssemblyFile="My.Shared.MSBuildTasks.dll" TaskName="My.Shared.MSBuildTasks.CompareBindingFiles"/>
</code></pre></div></div>
<p>We can then do the following in out build script!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!--
This target will export the current binding file, save as a temporary biding file and use a custom target to compare the exported file against the one weāre about to deploy.
A boolean value will be returned as IsValidBindingFile telling us if they are equal of not.
-->
<Target Name="IsValidBindingFile" Condition="$(ApplicationExists)=='True'">
<Message Text="Comparing binding file to the one deployed"/>
<Exec Command='BTSTask ExportBindings /ApplicationName:$(ApplicationName) "/Destination:Temp_$(BindingFile)"'/>
<CompareBindingFiles BindingFileToInstallPath="$(BindingFile)"
BindingFileDeployedPath="Temp_$(BindingFile)">
<Output TaskParameter="Value" PropertyName="IsValidBindingFile" />
</CompareBindingFiles>
<Message Text="Binding files is equal: $(IsValidBindingFile)" />
</Target>
<!--
This pre-build step runs only if the application exists from before. If so it will check if the binding file we try to deploy is equal to one deployed. If not this step will break the build.
-->
<Target Name="PreBuild" Condition="$(ApplicationExists)=='True'" DependsOnTargets="ApplicationExists;IsValidBindingFile">
<!--We'll break the build if the deployed binding files doesn't match the one being deployed-->
<Error Condition="$(IsValidBindingFile) == 'False'" Text="Binding files is not equal to deployed" />
<!--All other pre-build steps goes here-->
</Target>
</code></pre></div></div>
<p><img src="../assets/2009/12/rocket.jpg" style="float:right" /></p>
<p>So we now break the build if the binding file being deployed arenāt up-to-date!</p>
<p>This is <em>far</em> from rocket science but can potentially save you from making some stupid mistakes.</p>
BAM tracking data not moved to BAM Archive database2009-11-13T15:31:20+00:00http://richardhallgren.com/bam-tracking-data-not-moved-to-bam-archive-database<p>There are a few really good blog post that explains BAM ā like <a href="http://blogs.digitaldeposit.net/SARAVANA/post/2009/10/08/BAM-Production-environment-management.aspx">this</a> from Saravana Kumar and <a href="http://geekswithblogs.net/andym/archive/2009/05/21/132346.aspx">this</a> by Andy Morrison. They both do a great job explaining the complete BAM process in detail.</p>
<p>This post will however focus on some details in the last step of the process that has to do with archiving the data. Letās start with a quick walk-through of the whole process.</p>
<h3 id="bam-tracking-data-lifecycle">BAM Tracking Data lifecycle</h3>
<p><a href="../assets/2009/11/image3.png"><img src="../assets/2009/11/image_thumb.png" alt="image" /></a></p>
<ol>
<li>
<p>The tracked data is intercepted in the BizTalk process and written to the āBizTalk MsgBoxā database.</p>
</li>
<li>
<p>The TDDS service reads the messages and moves them to the correct table in the āBAM Primary Importā database.</p>
</li>
<li>
<p>The SSIS package for the current BAM activity has to be triggered (this is manual job or something that one has to schedule). When executing the job will do couple of things. <br />
1. Create a new partitioned table with a name that is a combination of the active table name and a GUID.</p>
</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2. Move data from the active table to this new table. The whole point is of course to keep the active table as small and efficient as possible for writing new data to.
3. Add the newly created table to a database view definition. It is this view we can then use to read all tracked data (including data from the active and partitioned tables).
4. Read from the āBAM Metadata Activitiesā table to find out the configured time to keep data in the BAM Primary Import database. This value is called the āonline windowā.
5. Move data that is older than the online window to the āBAM Archiveā database (or delete it if you have that [option](http://support.microsoft.com/kb/971984)).
</code></pre></div></div>
<p>Sound simple doesnāt it? I was however surprised to see <em>that my data was not moved to the BAM Archive database, even if it was clearly outside of the configured online window</em>.</p>
<h3 id="so-what-data-is-moved-to-the-bam-archive-database-then">So, what data is moved to the BAM Archive database then?</h3>
<p>Below there is a deployed tracking activity called āSimpleTrackingā with a online window of 7 days. Ergo, <em>all data that is older than 7 days should be moved to the BAM Archive database when we run the SSIS job for the activity</em>.</p>
<p><a href="../assets/2009/11/image8.png"><img src="../assets/2009/11/image_thumb5.png" alt="image" /></a></p>
<p>If we then look at the āBAM Completedā table for this activity we see that all the data is much older than 7 days as todayās date is ā13-11-2009ā.</p>
<p><em>So if we run the SSIS job these rows should be moved to the archive database. lets run the SSIS job. Right?</em></p>
<p><a href="../assets/2009/11/image9.png"><img src="../assets/2009/11/image_thumb6.png" alt="image" /></a></p>
<p>But when we execute the SSIS job the BAM Archive database is still empty! All we see are the partitioned tables that were created as part of the first steps of the SSIS job. <em>All data from the active table is however moved to the new partitioned table but not moved to the Archive database.</em></p>
<p><a href="../assets/2009/11/image10.png"><img src="../assets/2009/11/image_thumb7.png" alt="image" /></a></p>
<p><em>It turns out that the SSIS job does <strong>not at all look at the the āLast Modifiedā values</strong> of each row <strong>but on the āCreation Timeā of the partitioned table in the āBAM MetaData Partitionsā table</strong> that is shown below.</em></p>
<p><a href="../assets/2009/11/image11.png"><img src="../assets/2009/11/image_thumb8.png" alt="image" /></a></p>
<p>The idea behind this is of course to not have to read from tables that potentially are huge and find those rows that should be moved. But it also means that it will <em>take another 7 days before the data in the partitioned view is actually move to the archive database.</em></p>
<p>This might actually be a problem if you haven not scheduled the SSIS job to run from day one and you BAM Primary Import database is starting to get to big and you quickly have to move data over to archiving. All you then have to is of course to change that āCreation Timeā value in the BAM Metadata Partitions table so it is outside of the online window value for the activity.</p>
What kind of integration patters do you implement in BizTalk?2009-11-10T19:41:58+00:00http://richardhallgren.com/what-kind-of-integration-patters-do-you-implement-in-biztalk<p>I like to divide BizTalk based integrations into three different patterns.</p>
<ol>
<li>
<p>Point-to-point integration</p>
</li>
<li>
<p>Broker-based integration</p>
</li>
<li>
<p>ESB-based integration</p>
</li>
</ol>
<p>I am sure someone could come up with fancier names but I will in this post try and dig into each of them, explain what I mean by them. I will also try and highlight some issues with each of the patterns.</p>
<h3 id="point-to-point-integration">Point-to-point integration</h3>
<p><a href="../assets/2009/11/image.png"><img src="../assets/2009/11/image-thumb.png" alt="image" /></a> This is where a lot of us started. The idea is that the sending system has information and knowledge about the receiving system.</p>
<p>This usually means that the <em>messages are exported in a message format that is tailored to the format of the particular receiving systemās needs</em>. It also means that we usually <em>get one integration process for each receiving system there is</em>.</p>
<p>The example in the figure on the right shows a sending system that sends information about invoices to two different receiving systems (āSystem Aā and āSystem Bā). Using a point-to-point pattern in this scenario we end up with two different types of messages that are exported. Each of the exported messages that are suited and tailored to the format of the receiving system.</p>
<h4 id="issues">Issues</h4>
<p>The main problem with this kind of point-to-point integration, where the sending system has detailed knowledge about the receiving systems, is that <em>this knowledge translates into a coupling between the systems</em>. When we tie the export message format from the sending system to the format of the receiving, <em>all changes in the receiving system will also cause changes in the sending system</em>.</p>
<p>Suppose there is a sudden need to change the format of the receiving system - <em>as we use that format as our export format we now also have to change it there</em>.</p>
<p>Another problem is the <em>lack of agility</em>. In this invoice scenario all other system that also has the need of invoice based information has to get this by going all the way back to the sending system and develop a whole new <em>specific</em> integration - separate to the existing ones.</p>
<h3 id="broker-based-integration">Broker-based integration</h3>
<p><a href="../assets/2009/11/image1.png"><img src="../assets/2009/11/image-thumb1.png" alt="image" /></a>In the broker-based scenario the integration platform is used as a broker of messages.</p>
<p>This means that only **one canonical **format is exported from the sending system. The broker then handles the routing to the different systems and the transformation to the message formats that the receiving systems expects.</p>
<p><em>The main advantage between this approach - where the sending system do not know anything about the receiving systems ā and the point-to-point pattern is <strong>agility</strong></em>.</p>
<p>If there now is a need for invoice information in a third, new system, we do not have to change the export from the sending system (as long as we have all the information need that is) or develop a whole new integration. <em>All we have to do is to route the invoices so that they also are sent to the third system and transformed into the format that the system expects</em>. A new BizTalk map and port and we are done!</p>
<h4 id="issues-1">Issues</h4>
<p>In my point of view this approach to integration has a lot of advantages over the point-to-point integrations previously discussed. And in a lot of simpler, stabile scenarios it works just fine and is the way to go.</p>
<p>But in some scenarios it kind of breaks down and becomes hard to work with. The problems is related to configuration and how we define the routing information in BizTalk. In BizTalk we can either create an orchestration and āhardcodeā the process that defines which systems the messages should be sent to. We can also create a āmessagingā scenario where we configure this routing information in the different BizTalk port artifacts by setting up filters.</p>
<p>Regardless if we choose a āmessagingā or orchestration based solution the routing information becomes hard to update as the solution grow in size. We either get very complicated orchestrations or loads of ports to maintain.</p>
<p>Furthermore the whole process is very coupled to the one canonical schema which makes versioning and updates hard. If the canonical schema needs to be updated and we still need to be able to send information using the old schema (so we have a āversion 1ā and āversion 2ā of the schema side-by-side) all artifacts needs to be more or less duplicated and the complexity of the solutions grows fast.</p>
<p><em>This makes business agility hard and any changes takes long time to develop and deploy correctly.</em></p>
<blockquote>
<p>I guess these issues has more to do with how BizTalk works than the integration pattern itself - but this is a BizTalk blog!</p>
</blockquote>
<h3 id="esb-based-integration">ESB-based integration</h3>
<p><a href="../assets/2009/11/image2.png"><img src="../assets/2009/11/image-thumb2.png" alt="image" /></a>ESB-based integration in BizTalk is today achieved using <a href="http://msdn.microsoft.com/en-us/biztalk/dd876606.aspx">ESB Toolkit</a> from Microsoft.</p>
<p>One of the ideas of ESB-based integration is that the integration platform should not have hardcoded routing information. These routing rules should either be looked up at run time or travel with the actual payload of the message (called ādynamic routingā).</p>
<p>This in combination with having generic on- and off-ramps instead of loads of separate ports to maintain _promises to create more agile and configurable solutions _(called āLoosely coupled service compositionā and āEndpoint run-time discovery and virtualizationā).</p>
<p>The figure again shows the invoice scenario used previously. In this case we export a āInvoice 1.0ā-format from the sending system. The format is not directly bound to a schema in the port (as we are used to in BizTalk) but it is basically possible to send <strong>any</strong> message format to the on-ramp.</p>
<p>The on-ramp then identifies what kind of message it received (for example using the XML-namespace) and looks up the routing rules for that specific message (the message āitineraryā) in a repository.</p>
<p>In this scenario there could be rules to route the message to a orchestration or directly to a send port. _All the configuration for this port is however configured as part of the itinerary and applied at run-time on the generic off-ramp port. And as itineraries are simple XML documents they are super light to update and deploy in the repository! _</p>
<p>So if we now wanted to update the āInvoiceā-format to āversion 2.0ā all we would have to do is to create a new XML itinerary for the āInvoice 2.0ā message type and possibly create new orchestration to handle the new message type. No new ports, no new bindings etc, etc. The configuration and deployment would be a lot simpler than before! We would end up with a lot fewer artifacts to maintain.</p>
<p>**And **the itinerary for āInvoice 1.0ā would still be applied to all incoming Invoice 1.0 messages. <em>Thus we have achieved what used to be so hard with a lot less development power!</em></p>
<h4 id="issues-2">Issues</h4>
<p>With agility and dynamic capabilities comes complexity in debugging when something bad happens ā¦ I also feel that we give up a lot of validating and control capabilities that we had in the more schema-coupled patterns previously discussed.</p>
<p>I am new to this ESB-based model and I would love to hear your experiences, problems, stories etc!</p>
<p><em>I am however sure that this is the way to go and I would not be surprised if ESB like patterns will play an ever bigger role in future BizTalk versions!</em></p>
Third party BizTalk monitoring tools2009-08-11T15:18:11+00:00http://richardhallgren.com/third-party-biztalk-monitoring-tools<blockquote>
<p><strong>Update 2012-03-28</strong> <br />
When looking into BizTalk monitoring and overall governance tools for BizTalk, donāt miss <a href="http://www.biztalk360.com/">BizTalk360</a>. BizTalk 360 wasnāt available when this post was written and has some really compelling features.</p>
<p><strong>Update 2010-09-30:</strong> BizMon is now owned and developed by <a href="http://www.communicate.no">Communicate Norway</a>. They have renamed, and further developed the product, to IPM (Integration Monitoring Platform) ā check it out <a href="http://ipm.communicate.no/exciting-news">here</a>.</p>
</blockquote>
<p>Iāll start this post by clarifying two important things</p>
<ol>
<li>
<p>I am involved in the development and marketing of āBizMonā. Therefore I am biased and you have to decide for yourself if that affects the content of the post. As always it is best to <a href="http://bizmontool.com/buy">try it for yourself</a> and see if it is useful for you.</p>
</li>
<li>
<p>I have talked about BizTalk monitoring tools in a previous post and my goal then was then to start a an open source project. That did not happened and you can read why in the update to <a href="http://www.richardhallgren.com/aggregated-monitoring-of-biztalk-solutions-using-bizmon/">that post</a>.</p>
</li>
</ol>
<h3 id="why-monitoring-for-biztalk">Why āmonitoringā for BizTalk?</h3>
<p><img src="../assets/2009/08/image1.png" alt="image" /> I have worked as a BizTalk developer for many years but it was not until I really got in to maintaining a large integration solution that I realized that the tools I really needed was not there. I found myself using the following ātoolsā and techniques over and over again.</p>
<ol>
<li>Open the BizTalk Administration Console and query for suspended messages, running instances, routing errors etc, etc.</li>
</ol>
<p>But as I had to pull for this information it took time and discipline (two things Iām short of) to quickly find out when errors occurred.</p>
<ol>
<li>I used the HAT to try and find out when the last messages was sent and received on the different applications. This gave me a āguaranteeā that things worked as I accepted and that the solution had a āpulseā ā messages at least moved back and forward.</li>
</ol>
<p>The problem is that the HAT tool is bad and it is hard to find what one is looking for (It is a bit better in BizTalk 2009 but it is still tricky to get useful information out of it.)</p>
<ol>
<li>Some of the integrations in our environment used BAM to track messages and their state.</li>
</ol>
<p>The problem was that all solutions was developed by either myself or different consultants. This made it hard to get everyone to use the same tracking. It was also hard to convince management to go back and try and āinstrumentā old working integrations with BAM tracking.</p>
<p>At the same time as we had the ātoolsā and techniques mentioned above available, management had the following requirements for us.</p>
<ol>
<li>
<p>Start working on fixing an error <em>within 10 minutes</em> after it occurred <em>24/7 all 365 days</em> ā¦</p>
</li>
<li>
<p>Be able to delegate simple monitoring task to support personnel (a help desk).</p>
</li>
<li>
<p>Not have to actively āpullā for information but be quickly altered of errors and get the information āpushedā to us.</p>
</li>
</ol>
<p>The idea was that this would would save time as people donāt have to look for errors when everything is working fine. Time that people can use for other tasks ā¦</p>
<ol>
<li>Enable reporting so we can provide systems owners and other interested people with information on how much data has been sent received to the systems and parties they care about.</li>
</ol>
<p>All the above lead up to the realization that we needed some sort of tool.</p>
<h3 id="what-are-the-existing-options-for-biztalk-monitoring-tooling">What are the existing options for BizTalk monitoring tooling?</h3>
<p>At the time we started looking for options all we could find was <a href="http://www.microsoft.com/systemcenter/operationsmanager/en/us/default.aspx">System Center Operations Manager (SCOM)</a>. We looked at <a href="http://msdn.microsoft.com/en-us/library/ee308798%28BTS.10%29.aspx">SCOM BizTalk Management Pack</a> and decided that <em>for us</em> this was not the right solution. It was too big, too complicated and it would be to hard to get it to the what we wanted to do.</p>
<blockquote>
>
> The decision to not use SCOM I think was right for us. We wanted something leaner and more specialized. I am however **_not saying _**that it is the right decision for you.
>
>
>
> If you are successfully suing SCOM to monitor BizTalk I would love to [hear about it](mailto:richard.hallgren@gmail.com)!
>
> </blockquote>
<h3 id="what-we-ended-up-with">What we ended up with</h3>
<p>We ended up building <a href="http://bizmontool.com/">BizMon</a>. It does what we need and our help desk can now basically monitor about 100 different BizTalk application themselves. At the same time they do all the other support task they have to do. When something happens (and it does ā¦) they are the first to know. Some easy tasks they can solve themselves, otherwise they make sure to notify the users and quickly call the developer that knows more and can help them.</p>
<p>Support personnel can now also setup custom reports that users can subscribe to, all based on BAM that they now easily can interject tracking points in existing solutions ā both new and old ones.</p>
<p>As I said. This worked out out good and helped us. If you think that it could work for you as well ā <a href="http://bizmontool.com/buy">give it a try</a>.</p>
<p>I am also really interested to how you have solved similar requirements as we had with your own tool or other solutions.</p>
<h3 id="what-else-is-there">What else is there?</h3>
<p>Recently <a href="http://www.frends.com/">FRENDS</a> released a beta version of their <a href="http://www.frends.com/product/monitoring-technologies/">FRENDS Helium</a> product that looks promising could potentially solve a lot of the same issues that BizMon does and that I have discussed in this post.</p>
<p>Check it out and let us know what you think.</p>
Tips and tricks on BizTalk generated SOAP Web Services2009-06-16T08:30:32+00:00http://richardhallgren.com/tips-and-tricks-on-biztalk-generated-soap-web-services<p>Traditional SOAP Web Services might feel kind of old as more and more people move over to WCF. But a lot of integration projects still relay heavily on old fashion SOAP Web Services.</p>
<p>Using BizTalk generated Web Services however has a few issues and one needs to add a few extra steps and procedures to make them effective and easy to work with. This post aims to collect, link and discuss all those issues and solutions.</p>
<h3 id="1-building-and-deploying">1. Building and deploying</h3>
<p>BizTalk Server includes the āBizTalk Web Services Publishing Wizardā tool that integrates with Visual Studio. This is basically a tool to generate a <a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language">DSL</a> based script for generating web services.</p>
<p><a href="../assets/2009/06/image.png"><img src="../assets/2009/06/image-thumb.png" alt="image" /></a></p>
<p>The wizard collects information about what schema or a orchestration to expose, namespaces, names of service and method, where on IIS to publish the service etc, etc.</p>
<p>The output of the tool is then a xml file (a āWebServiceDescriptionā file) that has all the collected values in it.</p>
<p><a href="../assets/2009/06/image1.png"><img src="../assets/2009/06/image-thumb1.png" alt="image" /></a></p>
<p>As a final step Visual Studio uses the newly created description file as input to a class called WebServiceBuilder in the .NET Framework. It is this class that is responsible for interpreting the description, configure and generate the service.</p>
<p>A common procedure is to use the wizard and click thru it and input values for <strong><em>every</em></strong> single deployment. This is of course slow, error prone and stupid.</p>
<p>What is much better is to take a copy of the generated āWebServiceDescriptionā file, save it to your source control system and then programmatically pass the file to the WebServiceBuilder class as part of your deployment process. Possible changes to the details of the service can then be done directly in the description file.</p>
<p>I have seen this approach save lots of time and problems related to deployment.</p>
<ul>
<li>
<p>Paul Petrov has a great post on how to call the āWebServiceBuilderā class and pass the description file using C#. <br />
<a href="http://geekswithblogs.net/paulp/archive/2006/05/22/79282.aspx">http://geekswithblogs.net/paulp/archive/2006/05/22/79282.aspx</a></p>
</li>
<li>
<p>Michael Stephenson has a good post on how to used the āWebServiceBuilderā class via MSBuild. <br />
<a href="http://geekswithblogs.net/michaelstephenson/archive/2006/09/16/91369.aspx">http://geekswithblogs.net/michaelstephenson/archive/2006/09/16/91369.aspx</a></p>
</li>
</ul>
<h3 id="2-fixing-namespace">2. Fixing namespace</h3>
<p>Another annoying problem (Iād would actually go so far as calling it a bug) is the problem with the <em>bodyTypeAssemblyQualifiedName</em> value in the generated Web Service class.</p>
<p>This causes BizTalk to skip looking up the actual message type for the incoming message. As no message type exists for the message is in BizTalk mapping and routing on message types etc will fail. It is a know problem and there are solutions to it. I would also recommend take the extra time need to make this small āpost process stepā be part of your deployment process (see how <a href="http://www.richardhallgren.com/handle-the-bodytypeassemblyqualifiedname-soap-adapter-bug-in-msbuild-as-a-regex-ninja/">here</a>).</p>
<ul>
<li>
<p>Saravana Kumar discusses the problem and solutions in this great post. <br />
<a href="http://www.digitaldeposit.net/saravana/post/2007/08/17/SOAP-Adapter-and-BizTalk-Web-Publishing-Wizard-things-you-need-to-know.aspx">http://www.digitaldeposit.net/saravana/post/2007/08/17/SOAP-Adapter-and-BizTalk-Web-Publishing-Wizard-things-you-need-to-know.aspx</a></p>
</li>
<li>
<p>Richard Seroter has a short and well written post published. <br />
[http://blogs.msdn.com/richardbpi/archive/2006/09/15/Fixing-_2200<em>SOAP-_2F00</em>-Envelope-Schema_2200<em>-Error-In-BizTalk.aspx](http://blogs.msdn.com/richardbpi/archive/2006/09/15/Fixing-_2200_SOAP-_2F00</em>-Envelope-Schema_2200_-Error-In-BizTalk.aspx)</p>
</li>
<li>
<p>I have a post on how to solve the issue using MSBuild. <br />
<a href="http://www.richardhallgren.com/handle-the-bodytypeassemblyqualifiedname-soap-adapter-bug-in-msbuild-as-a-regex-ninja/">http://www.richardhallgren.com/handle-the-bodytypeassemblyqualifiedname-soap-adapter-bug-in-msbuild-as-a-regex-ninja/</a></p>
</li>
</ul>
<h3 id="3-pre-compiling">3. Pre-compiling</h3>
<p>By default the āWebServiceBuilderā class generates a web service <em>without</em> pre-compiling it. Usually this is not a problem. <em>But</em> in some cases were one really on the web service being online and give a quick response-message the performance problems in this approach can be a huge problem.</p>
<p>When generating the web service without pre-compiling it IIS has to compile the service and then keep the compiled service in memory. That means that when IIS releases the service from memory there is a latency before IIS re-compiled the service, loaded it into memory and executed it. This is a known problem and I have seen this āslow first hitā issue been a frequent question the different forums.</p>
<p>The solution is to use the aspnet_compiler.exe tool and pre-compile the service and the use those pre-compiled dlls as the service. IIS then never has to recompile it and will serve initial hits much faster.</p>
<p>Here is an example of how we defined a target to do this as part of our deployment process using MSBuild.</p>
<ol>
<li>
<p>Pre-compile the service into a new folder</p>
</li>
<li>
<p>Clean out the āoldā not compile service folder.</p>
</li>
<li>
<p>Copy the pre-complied service into the service folder</p>
</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><Target Name="CompileWeb">
<Message Text="Uses aspnet compiler to compile the service into a new folder. Then copies the compiled content back into its original place" />
<AspNetCompiler
PhysicalPath="$(WebSiteServicePath)InitiateProjectService\"
VirtualPath="/WebServiceName"
TargetPath="$(WebSiteServicePath)$(WebServiceName)Compiled\"
Force="true" />
<Folder.CleanFolder Path="$(WebSiteServicePath)$(WebServiceName)\"/>
<Folder.CopyFolder
Source="$(WebSiteServicePath)$(WebServiceName)Compiled\"
Destination="$(WebSiteServicePath)$(WebServiceName)\" />
</Target>
</code></pre></div></div>
<ul>
<li>Paul Petrov has two different articles here describing the process and also a different way that above on how to include the pre-compilation in you build process.</li>
</ul>
<p><a href="http://geekswithblogs.net/paulp/archive/2006/03/30/73900.aspx">http://geekswithblogs.net/paulp/archive/2006/03/30/73900.aspx</a>, <a href="http://geekswithblogs.net/paulp/archive/2006/04/19/75633.aspx">http://geekswithblogs.net/paulp/archive/2006/04/19/75633.aspx</a></p>
BAM ate my XML declaration!2009-05-28T12:14:49+00:00http://richardhallgren.com/bam-ate-my-xml-declaration<p>There are integrations which only purpose is to move a file <em>just as it is</em>. No advanced routing. No orchestration processing. No transformation. Just a simple port-to-port messaging scenario.</p>
<p>It is however still a good idea to monitor these just as one would monitor a more complicated integration. We use BAM to monitor all our integrations and to measure how many messages that has been processed in a integration. Using BAM monitoring in a simple solution as the above however has its issues ā¦</p>
<h3 id="setting-up-a-simple-test-solution">Setting up a simple test solution</h3>
<p><a href="../assets/2009/05/image.png"><img src="../assets/2009/05/image-thumb.png" alt="image" /></a></p>
<ol>
<li>
<p>The solution will move a XML file between two port called āSimpleTrackingReceivePortā and āSimpleTrackingSendPortā.</p>
</li>
<li>
<p>Both port have <em>PassThru pipelines configured</em>.</p>
</li>
<li>
<p><em>The XML file does not have a installed schema</em>. Remember we are just moving the file not actually doing anything with it.</p>
</li>
<li>
<p>A BAM tracking definition with one milestone called āStartPortā will be used. This will be mapped to the āPortStartTimeā property on both the receiving and sending port .</p>
</li>
</ol>
<p>Our tracking profile configuration will like below. Dead simple.</p>
<p><a href="../assets/2009/05/image1.png"><img src="../assets/2009/05/image-thumb1.png" alt="image" /></a></p>
<h3 id="so--whats-the-problem">So ā whatās the problem?</h3>
<p>Let us drop a XML message looking some like this.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="UTF-16"?>
<SimpleTest>
<SimpleContent Text="This is a test" />
</SimpleTest>
</code></pre></div></div>
<p>Remember that there is not a schema installed so we do not really have to worry about the structure of the file. It should just be āa fileā to BizTalk and everything should be transferred between the ports. Even if we drop a executable or whatever - it should just be transferred. <strong><em>Nothing should read or examine the file</em></strong> as itās just a pass thru!</p>
<p><strong><em>As soon as BAM tracking is configured on a port that is however not the case</em></strong>. Lets take a look at the file we receive on the other end of our integration.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><SimpleTest>
<SimpleContent Text="This is a test" />
</SimpleTest>
</code></pre></div></div>
<p><strong><em>BizTalk now removed our XML declaration!</em></strong> Basically it treated the message as a XML message and parsed the message as such while tracking it. Itā will also add the dreaded <a href="http://en.wikipedia.org/wiki/Byte-order_mark">Byte-Order-Mark</a> and fail any non-valid XML messages. The problem is that <strong><em>this is not the behavior what one expects</em></strong> and causes receiving systems that rely on the XML declaration to fail!</p>
<p>As we also donāt have a installed schema it is not possible to use a XMLTransmit pipeline to add the XML declaration and remove the BOM.</p>
<h3 id="what-to-do">What to do?</h3>
<p>If youād like to track a XML based message using BAM make sure you have the schema installed ā¦ Even if you are just using PassThru.</p>
<p>Is it a bug or just something one should expect? In my opinion it is at least <strong><em>very</em></strong> annoying!</p>
Receiving scheduled MsgBoxViewer-reports via e-mail2009-03-19T16:37:01+00:00http://richardhallgren.com/receiving-scheduled-msgboxviewer-reports-via-e-mail<p>I attended a session the other day at TechDays here in Sweden with Microsoft Escalation Engineer <a href="http://bizspace.blogspot.com/">Niklas Engfelt</a>. The session was about troubleshooting BizTalk and Niklas of course showed the wonderful <a href="http://blogs.technet.com/jpierauc/pages/what-is-biztalk-msgboxviewer.aspx">MsgBoxViewer</a> (MBV) tool by <a href="http://blogs.technet.com/jpierauc/default.aspx">Jean-Pierre Auconie</a>. If you havenāt tested and looked deeper into this tool you <em><strong>need</strong></em> to do so. Itās great!</p>
<p>I worked with the tool before but now I wanted to schedule the tool and to have MBV-reports e-mailed to relevant persons within the company on a weekly basis. This is quite easy to accomplish as MBV comes in two version. One GUI-based (shown below) version and one command-line based.</p>
<p><a href="../assets/2009/03/windowslivewriterreceivingscheduledmsgboxviewereportsviae-f7aeimage-12.png"><img src="../assets/2009/03/windowslivewriterreceivingscheduledmsgboxviewereportsviae-f7aeimage-thumb-5.png" alt="image" /></a></p>
<p>The command-line version is of course perfect for scheduling using the <a href="http://www.iopus.com/guides/winscheduler.htm">Windows Task Scheduler</a>.</p>
<p><a href="../assets/2009/03/windowslivewriterreceivingscheduledmsgboxviewereportsviae-f7aeimage-10.png"><img src="../assets/2009/03/windowslivewriterreceivingscheduledmsgboxviewereportsviae-f7aeimage-thumb-4.png" alt="image" /></a></p>
<p>If you feel uncomfortable running all the queries (there is <em>a lot</em> of them) on a schedule you can pick some you find important and configure the tool to only run those. Jean-Pierre has a post on how to do just that <a href="http://blogs.technet.com/jpierauc/archive/2009/03/11/mbv-how-to-run-only-some-specific-queries-in-the-console-version-of-mbv-btsdbcollect-exe.aspx">here</a>.</p>
<p>After MBV has completed all its queries and done its magic it will produce a html-report in the working folder (thatās the folder in the āStart inā field in the scheduled task example above).</p>
<p>We then use a tool called <a href="http://www.duodata.de/amlnt/index.htm">AutoMailer NT</a> (cost ā¬20 - there is a 30 days trial) to:</p>
<ol>
<li>
<p>Poll the working folder for a *.html report file.</p>
</li>
<li>
<p>Compress the file (using zip).</p>
</li>
<li>
<p>Send the report to a configured list of recipients.</p>
</li>
<li>
<p>Delete the report file.</p>
</li>
</ol>
<p>The AutoMailer NT installation is a bit rough (donāt miss to the <em>****</em><a href="http://www.duodata.de/amlnt/download.htm">separate download</a> (!) of the trial certificate). But once you have everything working itās great to have a fresh MBV report in you inbox every Monday telling you how your BizTalk environment is doing and possible issues to attend to.</p>
Better performance in batch imports to SQL Server using BizTalk2009-02-17T21:36:09+00:00http://richardhallgren.com/better-performance-in-batch-imports-to-sql-server-using-biztalk<p>During my years of BizTalk development Iāve been warned of a couple of scenarios that the product wouldnāt handle very well. Yesterday another of those scenarios turned out to kind of false and, if done right, not really a problem at all.</p>
<p>The scenario Iām talking about is a batch import of data to SQL Server using the SQL adapter. In my case the data is received as a flat text file containing a large number of rows. These rows should the be places inside a database table as one table-row per row in the flat file.</p>
<p>The common way of dealing with batch incoming data like this is to split (aka disassemble) it in the receive port using the Flat File Disassembler pipeline component (for a good example - look <a href="http://geekswithblogs.net/benny/archive/2006/02/05/68249.aspx">here</a>). Disassembling the data when receiving it is usually good practice to avoid running into <em>OutOfMemoryException</em> when <a href="http://msdn.microsoft.com/en-us/library/aa560481.aspx">dealing with big messages</a>.</p>
<p>Sometimes the requirements also forces one into reading each row to a separate message to be able to route and handle each messages in a unique way depending of itās content. If that so - this is a not a good post for you. <em>In this post Iāll discuss the scenario were all the data just needs to go as fast as possible from the text file into a single database table. No orchestration or anything, just a simple batch import.</em></p>
<h3 id="so-whats-the-problem-with-the-batch-import-scenario">So, whatās The problem with the batch import scenario?</h3>
<p>When I implemented similar batch import scenarios in the past I tried to practice good practice and split the data into separate files that I then filtered to the SQL adapter send port, one by one.</p>
<p><a href="../assets/2009/02/windowslivewriterperformanceinbatchimportstosqlserverusin-b997image-8.png"><img src="../assets/2009/02/windowslivewriterperformanceinbatchimportstosqlserverusin-b997image-thumb-3.png" alt="image" /></a></p>
<ol>
<li>The received flat file files has been split into thousands of small little message that one by one are sent to the SQL adapter send port.</li>
<li>The SQL adapter then parses each message into a SQL script that executes a store procedure and the message is finally inserted to the target database.</li>
</ol>
<p><strong>āSo whatās the problem?ā</strong> you then ask? <strong><em>Itās slow! Itās very slow!</em></strong> Each message gets stored a couple of times in the BizTalk database and each message is sent inside itās own <a href="http://en.wikipedia.org/wiki/Distributed_Transaction_Coordinator">DTC transaction</a> against the target database. And all this adds up ā¦</p>
<p>And after reading this <a href="http://seroter.wordpress.com/2008/09/03/interview-series-four-questions-with-alan-smith/">this interview</a> by <a href="http://seroter.wordpress.com/">Richard Seroter</a> with <a href="http://geekswithblogs.net/asmith/Default.aspx">Alan Smith</a> I also felt I was the only one having the problem either ā¦</p>
<blockquote>There are quite a few people asking about using BizTalk for heavy database integration, taking flat files, inserting the data in databases and processing it. SQL Server Integration Services (SSIS) does a much better job than BizTalk at this, and is worth looking at in those scenarios. BizTalk still has its uses for that type of work, but is limited be performance. The worst case I saw was a client who had a daily batch that took 36 hours to process using BizTalk, and about 15 minutes using SSIS. On another project I worked on they had used BizTalk for all the message based integration, and SSIS for the data batching, and it worked really well.
>
> </blockquote>
<p>Note: As Iāll described later in this post my import scenario went from something like 3-4 hours to 2 minutes (importing 10 MB). Alan talks about a 36 hours (!) import. I donāt know <em>anything</em> more about the scenario he mentions and it might not even be solved using the technique discussed below. Hopefully Alan might comment on the post and give us more details. ;)</p>
<h3 id="how-can-we-get-better-performing-imports-using-biztalk">How can we get better performing imports using BizTalk?</h3>
<p>As the import scenario we described doesnāt involve any orchestration but is a pure messaging scenario and we do all the transformation on the ports we donāt really have to worry about _OutOfMemoeyExceptions _even though the message is quite big.</p>
<blockquote>**Large message transformation.** In previous versions of BizTalk Server, mapping of documents always occurred in-memory. While in-memory mapping provides the best performance, it can quickly consume resources when large documents are mapped. In BizTalk Server 2006, large messages will be mapped by the new large message transformation engine, which buffers message data to the file system, keeping the memory consumption flat. ([Source](http://www.microsoft.com/technet/prodtechnol/biztalk/2006/evaluate/overview/default.mspx))
>
> </blockquote>
<p>Another reason for splitting the message was for it to work with the SQL adapter. When setting up the SQL adapter to work with a store procedure the adapter expects a message that looks something like the below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ns0:ImportDataSP_Request xmlns:ns0="http://FastSqlServerBatchImport.Schemas.SQL_ImportDataSP">
<ImportData Name="Name 1" Value="1"></ImportData>
</ns0:ImportDataSP_Request>
</code></pre></div></div>
<p>This tells us that the store procedure called is āImportDataā with āName 1ā as the value for the āNameā parameter and ā1ā as the value for the parameter called āValueā in the stored procedure. So each little separate message would get mapped on the send port into something like this.</p>
<p>What I however didnāt know until I read <a href="http://connectedthoughts.wordpress.com/2008/09/09/multiple-stored-procedure-calls-using-the-biztalk-sql-adapter-without-a-loop-shape/">this post</a> was that the message I send to the SQL adapter port just as well could look like this!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ns0:ImportDataSP_Request xmlns:ns0="http://FastSqlServerBatchImport.Schemas.SQL_ImportDataSP">
<!-- TWO rows!!! -->
<ImportData Name="Name 1" Value="1"></ImportData>
<ImportData Name="Name 2" Value="2"></ImportData>
</ns0:ImportDataSP_Request>
</code></pre></div></div>
<p>So basically we can have as <strong><em>many store procedure calls as we want in one single file</em></strong> that then can send to the SQL adapter send port!</p>
<p><em><strong><a href="http://en.wikipedia.org/wiki/Eureka_(word)">Eureka!</a> **__</strong>This means that we donāt have to split the incoming file! We can keep it as one big single file and just transform it to a huge file containing separate nodes that we send to the SQL Adapter send port! The SQL adapter will then parse this into separate store procedure calls for us.**</em></p>
<p><a href="../assets/2009/02/windowslivewriterperformanceinbatchimportstosqlserverusin-b997image-10.png"><img src="../assets/2009/02/windowslivewriterperformanceinbatchimportstosqlserverusin-b997image-thumb-4.png" alt="image" /></a><strong>__</strong></p>
<h3 id="is-it-really-any-faster">Is it really any faster?</h3>
<p>As the technique above drastically reduced the amount of database communication needed I knew itād be much faster. Some initial testing shows that <strong><em>an import of a file containing somewhere around 55 000 rows (about 10 MB) into our article database went from 3-4 hours to under two minutes!</em></strong></p>
<h3 id="see-for-yourself">See for yourself!</h3>
<p>In <a href="http://www.richardhallgren.com/blogfiles/SqlServerBatchImport sample.zip">this sample solution</a> I have a text file containing 2 600 rows. Iāve then created two separate projects in a solutions. One that splits the messages into separate messages (called āSlowImportā) and one that just transforms it and send it as one message to the send port (called āFastImportā). One takes 1:50 minutes and 2 seconds on my development machine ā¦ I wonāt tell you which one is the faster one ā¦</p>
<p>Test it for yourself and let me know what you think.</p>
Aggregated monitoring of BizTalk solutions using 'BizMon'2009-01-06T15:25:20+00:00http://richardhallgren.com/aggregated-monitoring-of-biztalk-solutions-using-bizmon<blockquote>
>
> **Update 2010-09-30:** BizMon is now owned and developed by [Communicate Norway](http://www.communicate.no). They have renamed, and further developed the product, to IPM (Integration Monitoring Platform) ā check it out [here](http://ipm.communicate.no/exciting-news).
>
> </blockquote>
<blockquote>
>
> _**Update 2009-08-11: **This project turned out to be far more complicated and bigger than I first expected (ever heard that before?). Due to that and the fact that we wanted to have a company behind that could offer full-time support and stability āBizMonā has been released as a commercial product that you can find [here](http://bizmontool.com/). _
>
>
>
> _I love to get some [help from you](http://bizmontool.com/we-have-a-rtm-version)**** to test it and make it as good as possible. Even if it is commercial and cost money we have a free alternative for small environments and we work hard to keep the license price as low as possible._
>
> </blockquote>
<p><em>****</em></p>
<blockquote>
>
> _**Update 2009-02-25:** In the original post I said I'd post more on the architecture and the code during February 09. I'm however current struggling getting the needed legal rights etc, etc to be able to talk further about the "BizMon"-solution. It was harder than I thought ... I'll get back to posing on the subject as soon as I have that sorted._
>
> </blockquote>
<p>Integration of enterprise processes often ends up being very business critical. If a integration fails delivering the messages it was supposed to it usually means the business will be affected in a very negative way (for example losing money or delivering bad service). That of course means that monitoring the status of the integrations soon becomes very important (if youāre not into getting yelled at or potentially loosing your job).</p>
<p>Strangely enough <em><strong>BizTalk Server 2006 R2 _in my humble opinion_ doesnāt come with the right tool to efficiently monitoring big enterprise integration solutions!</strong></em></p>
<h3 id="what-do-i-mean-by-monitoring">What do I mean by monitoring?</h3>
<p><a href="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-20.png"><img src="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-thumb-9.png" alt="image" /></a> Before I get myself deeper into trouble Iād like to define what I mean by monitoring. I think monitoring a BizTalk integration solution could be divided into four categories.</p>
<ol>
<li>
<p><strong>Infrastructure **(traditional)</strong> <br />
**This is the easy one and one that IT-pros and alike are used to monitor. Hardware status, network traffic, disk space, event logs etc all fall under this category. If the storing area for the databases start running low on memory we can be pretty sure itāll eventually effect the integration somehow.</p>
</li>
<li>
<p>**BizTalk infrastructure <br />
**This is where it starts getting a bit trickier. This category includes the status of receive locations, orchestrations, host instances and send ports. If a receive location is down no messages will be picked up (but we can also be sure of not getting any suspended messages).</p>
</li>
<li>
<p>**Suspended messages <br />
**As most reader of this blog probably know suspended message is due to some sort of failure in BizTalk. It can be an actually exception in code or something that went wrong while trying to send messages. Itās however and important category to monitor.</p>
</li>
<li>
<p>**Heartbeat (monitoring actual successful traffic) <br />
**While the points 1-3 above focuses on errors and that things being inactive this category actually monitors that the integration <em>runs as expected</em>.</p>
</li>
</ol>
<p>To me this final point is almost the most important one. What I mean is that if everything runs as expected and weāre sending the expected amount of messages in the right pace everything else must be ok - right? Itās however the one that in my experience almost always overlooked!</p>
<h3 id="what-do-you-mean-not-the-right-tools-to-monitor-we-have-loads-of-tools-in-biztalk-2006-r2">āWhat do you mean āNot the right tools to monitorā? We have loads of tools in BizTalk 2006 R2!ā</h3>
<p>OK. So letās see what tools we have available actually monitor the categories above.</p>
<ol>
<li>
<p><strong>Infrastructure **(traditional)</strong>** <br />
I wonāt discuss this kind of monitoring in this post. There are loads of tools (all from the <a href="http://www.microsoft.com/systemcenter/operationsmanager/en/us/default.aspx">huge expensive enterprise ones</a> to plenty of <a href="http://www.nagios.org/">good open-source alternatives</a>) for this and youāre probably already using one or several of them already.</p>
</li>
<li>
<p>**BizTalk infrastructure <br />
**There are a couple of way of achieving this. One of the is to use the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=389FCB89-F4CF-46D7-BC6E-57830D234F91&displaylang=en">Microsoft BizTalk Server Management Pack for Operation Manager</a>. It does however of course require that you have invested in System Center Operation Manager already ā¦</p>
</li>
</ol>
<p>Another way is to either use the <a href="http://technet.microsoft.com/en-us/library/microsoft.biztalk.explorerom.aspx">ExplorerOM classes</a> or connecting directly to the BizTalk configuration database and code your own report of some sort.</p>
<p>The final (and most common way in my experience) is to try and document the correct configuration and settings and then have someone check these manually (if youāre that person I feel for you ā¦).</p>
<ol>
<li>**Suspended messages <br />
**Suspended messages are of course very important to monitor and itās for some reason also the first thing developers think of monitoring when developing BizTalk integration (maybe because of the fact that theyāre similar to traditional exceptions in software). There are also here a couple of different ways to solve the problem.</li>
</ol>
<p><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=389FCB89-F4CF-46D7-BC6E-57830D234F91&displaylang=en">Microsoft BizTalk Server Management Pack for Operation Manager</a> mentioned above has the functionality to monitor and altering on suspended messages.</p>
<p>BizTalk Server fires <em><a href="http://msdn.microsoft.com/en-us/library/aa547324.aspx">the MSBTS_ServiceInstanceSuspendedEvent</a></em> WMI event every time a service instance gets suspended. Itās fully possible to write a service that watches for this event and then for example sends some sort of alert. Darren Jefford has an example on how do something like that in <a href="http://blogs.msdn.com/darrenj/archive/2004/03/30/104135.aspx">this post</a>.</p>
<p>In BizTalk 2006 <a href="http://msdn.microsoft.com/en-us/library/aa578516.aspx">Failed Message Routing</a> was introduced. This gives the developer the possibility to subscribe to suspended messages. These can then for example be sent out to file system or written to a database. <a href="http://msdn.microsoft.com/en-us/library/cc487894.aspx">Microsoft ESB Guidance for BizTalk Server 2006 R2</a> Exception management component uses this approach. The problem with this approach is however that the message is moved out of BizTalk and one loses all the built in possibilities of resending them etc.</p>
<ol>
<li>**Heartbeat (monitoring actual successful traffic)</li>
</ol>
<p><a href="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-4.png"><img src="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-thumb-1.png" alt="image" /></a>As I said before I think this is a very important metric. If you can see that messages travel through BizTalk in a normal rate things much be pretty ok ā right? Without doing to much coding and developing you own pipeline components for tracking etc there are two options.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> **
</code></pre></div></div>
<p>The first one is of course using the <a href="http://msdn.microsoft.com/en-us/library/ms943738.aspx">Health and Activity Tracking</a> tool (HAT). This shows a simple view of receives, processed and sent messages. I hate to say it but the HAT tool is <em><strong>bad</strong></em>. Itās slow, itās hard to use, itās hard to filter information, it times out, it doesnāt aggregate information, itās basically almost useless ā¦ (Just to make one thing clear: I make my living working with BizTalk and <em>I really enjoy</em> the product but tracking and monitoring is really one of itās ugly sides. I hate to say it.)</p>
<p>The other option is to develop a simple <a href="http://msdn.microsoft.com/en-us/library/aa972199.aspx">BAM tracking</a> profile to monitoring the send and receive port ports of the different processes.</p>
<p>So to repeat what I said earlier: no I donāt think BizTalk comes with the right tool to monitor integration solutions. I do however think that the platform has the capabilities to create something that could close that gap in the product.</p>
<h3 id="what-i-need">What I need!</h3>
<p>Much of whatās discussed in this post can be solved using the <a href="http://msdn.microsoft.com/en-us/library/ms943596.aspx">BizTalk Administrations Console</a> (to manually monitor BizTalk infrastructure status) or in the <a href="http://technet.microsoft.com/en-us/library/ms943738.aspx">Health and Activity Tracking</a> tool (to manually monitor traffic). <em><strong>The aim of this post is however to discuss the possibilities to use this information, aggregate it and give the persons responsible for monitoring integration a dashboard that shows the current status of all integrations within the enterprise.</strong></em></p>
<p><a href="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80monitor-dashboard-2.jpg"><img src="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80monitor-dashboard-thumb.jpg" alt="Monitor DashBoard" /></a></p>
<p>The dashboard monitor application need the following main features.</p>
<ul>
<li>
<p>In one single screen give an overview of the overall status of all the integrations. By status I mean if there are ports, orchestration or host instances that arenāt running that should be running or if there is any suspended traffic on that particular integration.</p>
</li>
<li>
<p>The possibility to show detailed information for a specific integration on what artifacts (ports, host instances etc) that are/arenāt running. How much traffic thatās been sent/received via the integration. When traffic was sent/received and if thereās any suspended messages on the integration.</p>
</li>
<li>
<p>The option to filter exclude specific artifacts from monitoring (for example receive locations thatās usually turned off etc).</p>
</li>
<li>
<p>Setting up monitoring by for example email and also define what integrations to be included in one specific monitoring (different persons are usually responsible for monitoring different integrations).</p>
</li>
</ul>
<h3 id="introducing-bizmon">Introducing āBizMonā</h3>
<p>Based on the needs and ārequirementsā above Iāve started developing a application. The idea is to release it as open-source as soon as I get to a first stable version (Iād be very interested in help on practical details on how to do so). For now Iāll demonstrate it by showing some screenshots. The application is a web application based on <a href="http://www.asp.net/mvc/">ASP.NET MVC</a>.</p>
<h3 id="screenshot-applications-page">Screenshot: āApplicationsā page</h3>
<p><a href="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-10.png"><img src="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-thumb-4.png" alt="image" /></a></p>
<p>The above image shows a screenshot from the start page of the BizMon-application that shows the aggregated status of the entire BizTalk group itās connected to. The applications is build to monitor one BizTalk group and the shown page displays all <a href="http://msdn.microsoft.com/en-us/library/aa560585.aspx">applications</a> within that <a href="http://msdn.microsoft.com/en-us/library/ms962428.aspx">BizTalk group</a>.</p>
<p>In the example image the two first rows have an OK status. That means that all of the monitored artifacts (receive locations, send ports, orchestrations and host instances) <em>within</em> that application are in a running and OK status. <br />
The yellow line on the <em>YIT.NO.Project</em>-application indicates a warning. That means that all the artifacts are in a OK status <em>but</em> thereāre suspended messages within that application. The red line indicates that one or more of the monitored artifacts are in a inactive status.</p>
<p>Each row and application show when the last message on that application was received and/or sent. It also show how many suspended messages exists and when the last message got suspended.</p>
<h3 id="screenshot-application-detail-page">Screenshot: āApplication-detailā page</h3>
<p><a href="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-12.png"><img src="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-thumb-5.png" alt="image" /></a></p>
<p>When clicking on a application on the main page previously shown the application-detail page is displayed for that application. This page shows detailed information on each of the artifacts within that application. I also shows suspended messages and the date and time of the last suspended.</p>
<p>It also displays a graph showing how many messages that has been processed by each of the ports. Currently the graph can view data from the last 7 days. In the screenshot above data from the 6th of January is shown and as itās set to display data for a specific day the data is grouped in hours of that day. Itās also possible to view the aggregated data from all the traced days as show below. When viewing data from all days the graphs is grouped by days.</p>
<p>(The graph only shows data from the 6th of January as this is from test and there was no traffic of the previous days but Iām sure you get the idea ā¦)</p>
<p><a href="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-14.png"><img src="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-thumb-6.png" alt="image" /></a></p>
<h3 id="screenshot-application-detail-page-with-inactive-artifacts">Screenshot: āApplication-detailā page with inactive artifacts</h3>
<p><a href="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-18.png"><img src="../assets/2009/01/windowslivewriteraggregatedmonitoringofbiztalksolutions-dd80image-thumb-8.png" alt="image" /></a></p>
<p>This final page show details of an application with some inactive artifacts. The small cross highlighted by the arrow in the image show the possibility to filter out a single artifact from monitoring. If an excluded artifacts is failing the overall status of the application will still be OK and no alerts will be sent.</p>
<h3 id="help">Help!</h3>
<p>Iād love to <strong><em>get some input and feedback</em></strong> on all this. <em><strong>What do you think could be useful, what do you think wonāt? Do you know of something similar, how do you solve this kind of monitoring?</strong></em></p>
<p>Iād also like to know any suitable placed to publish the code as an open-source project or is the best thing to just release it here on the blog? What do you think? Use the comments or <a href="mailto:richard.hallgren@gmail.com">send me a mail</a>.</p>
<h3 id="whats-next">Whatās next?</h3>
<p>I have a few thing on the alerts part of the application left and then Iāll release a first version. Iām hoping that could happened at the <strike>end of February 09</strike> (look at the update at the top of the post) . Make sure to <a href="mailto:richard.hallgren@gmail.com">let me know what you think</a>!</p>
<p>Iāll publish a follow-up post discussing the technical details and the architecture more in detail shortly.</p>
Handle the 'bodyTypeAssemblyQualifiedName' SOAP Adapter bug in MSBuild as a RegEx ninja2008-11-12T12:53:32+00:00http://richardhallgren.com/handle-the-bodytypeassemblyqualifiedname-soap-adapter-bug-in-msbuild-as-a-regex-ninja<p>This is a very specific problem but Iām sure some of you stumbled over it. When disassembling a XML message in a SOAP port BizTalk canāt read the message type. This causes problems when for example trying to handle an envelope message and split it to smaller independent messages in the port. Itās a known problem discussed <a href="http://blogs.msdn.com/richardbpi/archive/2006/09/15/Fixing-_2200_SOAP-_2F00_-Envelope-Schema_2200_-Error-In-BizTalk.aspx">here</a> and <a href="http://www.digitaldeposit.net/saravana/post/2007/08/17/SOAP-Adapter-and-BizTalk-Web-Publishing-Wizard-things-you-need-to-know.aspx">here</a> (you also find information about it in the <a href="http://download.microsoft.com/download/3/7/6/376a6f6c-8c97-4ab5-9d5a-416c76793fbb/bts06developerstroubleshootingguide.doc">BizTalk Developerās Troubleshooting Guide</a>) and the solution is to make a small change in the generated web service class. Below is a small part of he generated class.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//[cut for clarity] ...
Microsoft.BizTalk.WebServices.ServerProxy.ParamInfo[] outParamInfos = null;
string bodyTypeAssemblyQualifiedName = "XXX.NO.XI.CustomerPayment.Schemas.r1.CustomerPayments_v01, XXX.NO.XI.CustomerPaym" +
"ent.Schemas.r1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ac564f277cd4488" +
"e";
// BizTalk invocation
this.Invoke("SaveCustomerPayment", invokeParams, inParamInfos, outParamInfos, 0, bodyTypeAssemblyQualifiedName, inHeaders, inoutHeaders, out inoutHeaderResponses, out outHeaderResponses, null, null, null, out unknownHeaderResponses, true, false);
}
}
}
</code></pre></div></div>
<p>Basically the problem is that the generated code puts the wrong _DocumentSpecName _property in the message context. Iāll not dicusses the problem in detail here but Saravana Kumar does thorough dissection of the problem in <a href="http://www.digitaldeposit.net/saravana/post/2007/08/17/SOAP-Adapter-and-BizTalk-Web-Publishing-Wizard-things-you-need-to-know.aspx">his post</a> on it.</p>
<p>The solution is to update the <em>bodyTypeAssemblyQualifiedName</em> to set a null value. That will cause the <em>XmlDiassasemler</em> to work as weāre used to and expect.</p>
<blockquote>
>
> If the value _null_ is passed instead of _bodyTypeAssemblyQualifiedName_, SOAP adapter won't add the _DocumentSpecName_ property to the context. Now, when we configure our auto-generated SOAP_ReceiveLocation_ to use _XmlReceive_ pipeline, the _XmlDisassembler_ component inside _XmlReceive_ will go through the process of automatic dynamic schema resolution mechanism, pick up the correct schema and promotes all the required properties (distinguished and promoted) defined in the schema and it also promotes the _MessageType_ property.
>
>
>
> **From:** [http://www.digitaldeposit.net/saravana/post/2007/08/17/SOAP-Adapter-and-BizTalk-Web-Publishing-Wizard-things-you-need-to-know.aspx](http://www.digitaldeposit.net/saravana/post/2007/08/17/SOAP-Adapter-and-BizTalk-Web-Publishing-Wizard-things-you-need-to-know.aspx)
>
> </blockquote>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//[cut for clarity] ...
Microsoft.BizTalk.WebServices.ServerProxy.ParamInfo[] outParamInfos = null;
string bodyTypeAssemblyQualifiedName = null;
// BizTalk invocation
this.Invoke("SaveCustomerPayment", invokeParams, inParamInfos, outParamInfos, 0, bodyTypeAssemblyQualifiedName, inHeaders, inoutHeaders, out inoutHeaderResponses, out outHeaderResponses, null, null, null, out unknownHeaderResponses, true, false);
}
}
}
</code></pre></div></div>
<p>But if you have an automated deployment process you probably use <a href="http://geekswithblogs.net/michaelstephenson/archive/2006/09/16/91369.aspx">MSBuild to generate your Web Services</a>. Then is soon becomes <strong>_very _</strong>annoying to remember to update the .cs-file again and again for every deployment. <strong>So how can we script that update?</strong></p>
<p>First we need to find a regular expression to find the right values. With some help from <a href="http://stackoverflow.com/">StackOverflow</a> (letās face it, there are some <strong><em>crazy</em></strong> regular expressions skills out there ā¦) I ended up on the following.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(?<=string\sbodyTypeAssemblyQualifiedName\s=\s)(?s:[^;]*)(?=;)
</code></pre></div></div>
<p><img src="../assets/2008/11/windowslivewriterhandlethebodytypeassemblyqualifiednameso-adf4ninja5-thumb.jpg" alt="ninja5" /> If youāre not a RegEx ninja the line above does something like this:</p>
<ol>
<li>
<p>After the string āstring bodyTypeAssemblyQualifiedName = ā</p>
</li>
<li>
<p>turn on single line (treat ā\r\nā as any other character) ( this is what ā(?s: )ā does)</p>
</li>
<li>
<p>match every character that is not a semicolon</p>
</li>
<li>
<p>until a single semicolon is reached.</p>
</li>
</ol>
<p>Then I used a task from the <a href="http://www.codeplex.com/sdctasks">SDC Task library</a> (you probably already use this if youāre using MSBuild and BizTalk). More specially we use the <em>File.Replace</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><Target Name="FixSOAPServiceCode">
<File.Replace
Path="$(WebSiteServicePath)CustomerPaymentService\App_Code\CustomerPaymentService.asmx.cs"
Force="true"
NewValue="null"
RegularExpression="(?&lt;=string\sbodyTypeAssemblyQualifiedName\s=\s)(?s:[^;]*)(?=;)">
</File.Replace>
</Target>
</code></pre></div></div>
<p>Now this task is part of the build script and called right after the tasks that generates the web service. This saves me a lot of manual work and potential errors!</p>
Using BizUnitExtensions to poke around in some XML2008-10-30T14:59:17+00:00http://richardhallgren.com/using-bizunitextensions-to-poke-around-in-some-xml<p>Iāll start by saying that I really (like in āreally, <strong><em>really!</em></strong>ā) like <a href="http://www.codeplex.com/bizunit">BizUnit</a>! BizUnit in combination with <a href="http://msdn.microsoft.com/en-us/library/wea2sca5.aspx">MSBuild</a>, <a href="http://www.nunit.org/index.php">NUnit</a> and <a href="http://confluence.public.thoughtworks.org/display/CCNET/Welcome+to+CruiseControl.NET">CruiseControl.NET</a> has really changed the way work and how I <em>feel</em> about work in general and BizTalk development in particular.</p>
<p>If you havenāt started looking into what for example MSBuild can do you for you and your BizTalk build process youāre missing out on something great. The time spent on setting up a automatic build process is time well spent - take my word for it!</p>
<p>But build processes isnāt was this post is supposed to be about. This post is about one of the few limitations of BizUnit and the possibilities to work around one of those in particular.</p>
<blockquote>BizUnit is a test framework that is intended to test Biztalk solutions. BizUnit was created by Kevin.B.Smith and can be found on [this CodePlex space](http://www.codeplex.com/bizunit) . BizUnit has quite a significant number of steps that have nothing to do with Biztalk per se and can be used for any integration project testing.
>
> </blockquote>
<blockquote>[![note](../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286note-thumb.gif)](../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286note-2.gif)If you have used BizUnit before and need an introduction before reading further, start [here](http://www.codeproject.com/KB/biztalk/BizUnit2006.aspx), [here](http://www.codeplex.com/bizunit) or [here](http://biztalkia.blogspot.com/2007/03/getting-started-with-nunit-and-bizunit.html) - they're all excellent articles.
>
> </blockquote>
<p>As stated BizTalk has quite a significant number of steps but to my knowledge itās missing a step to change and update file from within the test script. This step and a couple of other are added in separate fork-project to BizUnit called <a href="http://www.codeplex.com/bizunitextensions">BizUnitExtensions</a>.</p>
<blockquote>This project [_BizUnitExtension_] aims to provide some more test step libraries, tools and utilities to enhance the reach of BizUnit. Here you can find some enhancements/extensions to the steps in the base libraries , new steps, support applications, tutorials and other documentation to help you understand and use it....This project is currently owned and contributed to by Santosh Benjamin and Gar Mac CrĆostaand. Our colleagues have also contributed steps and suggestions. We welcome more participation and contributions.
>
> </blockquote>
<p>Amongst other steps (some for Oracle DBs etc) BizUnitExtensions adds a <a href="http://www.codeplex.com/bizunitextensions/Wiki/View.aspx?title=BizUnit%20Extensions&referringTitle=Documentation">XmlPokeStep</a>!</p>
<blockquote>**XmlPokeStep:** This step is modelled on the lines of the NAnt XmlPoke task The XmlPokeStep is used to update data in an XML file with values from the context This will enable the user to write tests which can use the output of one step to modify the input of another step.
>
> </blockquote>
<p>A cool thing about BizUnitExtensions is that it really just extends BizUnit. Youāll continue to run on the BizUnit dll:s when you use steps form BizUnit and just use the BizUnitExtensions code when you actually use some of steps from that library.</p>
<p>The example below shows how we first use an ordinary BizUnit task to validate and read a value from a file. We then use BizUnitExtension to gain some new powers and update the file with that value we just read.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!āOrdinary BizUnit step to validate a file ā>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileValidateStep">
<Timeout>5000</Timeout>
<Directory>..\..\ReceiveRequest</Directory>
<SearchPattern>*Request.xml</SearchPattern>
<DeleteFile>false</DeleteFile>
<ContextLoaderStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.XmlContextLoader">
<XPath contextKey="messageID">/*[local-name()=āSystemRequestā]/ID</XPath>
</ContextLoaderStep>
</TestStep>
<!āUse BizUnitExtensions to poke the value and change it ā>
<TestStep assemblyPath="BizUnitExtensions.dll" typeName="BizUnit.Extensions.XmlPokeStep">
<InputFileName>..\..\SystemResponse.xml</InputFileName>
<XPathExpressions>
<Expression>
<XPath>/*[local-name()=āSystemResponseā]/ID</XPath>
<NewValue takeFromCtx="messageID"></NewValue>
</Expression>
</XPathExpressions>
</TestStep>
</code></pre></div></div>
<p>This of course means that all you need to extend you current test steps and gain some cool new abilities is to add another assembly to you test project<img src="../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286image-8.png" alt="![image](../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286image-thumb-3.png)" /></p>
<h3 id="using-bizunitextensions-in-a-real-scenario">Using BizUnitExtensions in a ārealā scenario</h3>
<p>An scenario when this can be useful is the following example were we need to test some message correlation.<a href="../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286image-2.png"><img src="../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286image-thumb.png" alt="image" /></a></p>
<ol>
<li>
<p>A message request is received via a web service.</p>
</li>
<li>The message is sent to a queue via an orchestration in BizTalk. <em>To be able to correlate the response <strong>a message id is added to the message request</strong> sent to the back-end system.</em></li>
<li>
<p>A message response is sent from the back-end system using a second queue. <em>The response message contains the same message id as the incoming request contained</em>.</p>
</li>
<li>BizTalk correlates the message back to the web service using the message id.</li>
</ol>
<p>So how can we <strong><em>now test this</em></strong>? The steps should be something like the below.</p>
<blockquote>
>
> [![note](../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286note-thumb-1.gif)](../assets/2008/10/windowslivewriterusingbizunitextensionstopokesomexml-d286note-4.gif) Notice that we read and write to the file system in the example. Once deployed to test these send ports and receive location will be reconfigured to use the queuing adapter. But for testing the scenario the file system works just fine a simplifies things IMHO.
>
> </blockquote>
<ol>
<li>Send a request message using BizUnit and the <em>HttpRequestResponseStep</em>. Make sure it runs <em><strong>concurrently</strong></em> with the other steps and then wait for a response (using the _runConcurrently-_attribute on the step).</li>
<li>Configure the send port so the orchestration that added the generated message id writes the message to a folder. Use the <em>FileValidateStep</em> and a nested <em>XmlContextLoader</em> to read the message from the folder and write the message id the context.</li>
<li>Use the context and the <em>XmlPokeStep</em> from BizUnitExtensions to update a response message template with the message id from the request message (this is of course needed so we can correlate the response message back to the right orchestration).</li>
<li>Copy the update response message template using the <em>FileCreateStep</em> to the folder that is monitored by the the receive location used for reading responses.</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><TestCase testName="TestCorrelationTest">
<TestSetup>
<!āClean up!ā>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\ReceiveRequest</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\SendResponse</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
</TestSetup>
<TestExecution>
<!āPost a request message on the SOAP port. Run it Concurrentlyā>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.HttpRequestResponseStep" runConcurrently="true">
<SourcePath>..\..\WebRequest.xml</SourcePath>
<DestinationUrl>http://localhost:8090/BizTalkWebService/WebService1.asmx?op=WebMethod1</DestinationUrl>
<RequestTimeout>15000</RequestTimeout>
</TestStep>
<!āRead the system request message and read the generaed id to the contextā>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileValidateStep">
<Timeout>5000</Timeout>
<Directory>..\..\ReceiveRequest</Directory>
<SearchPattern>*Request.xml</SearchPattern>
<DeleteFile>false</DeleteFile>
<ContextLoaderStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.XmlContextLoader">
<XPath contextKey="messageID">/*[local-name()=āSystemRequestā]/ID</XPath>
</ContextLoaderStep>
</TestStep>
<!āIf we have the file in source control it might be read-only -> remove that attributeā>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.ExecuteCommandStep">
<ProcessName>attrib</ProcessName>
<ProcessParams>SystemResponse.xml -r</ProcessParams>
<WorkingDirectory>..\..\</WorkingDirectory>
</TestStep>
<!āUpdate our response template (using BizUnitExtensions) and add the message id that we read into the the contextā>
<TestStep assemblyPath="BizUnitExtensions.dll" typeName="BizUnit.Extensions.XmlPokeStep">
<InputFileName>..\..\SystemResponse.xml</InputFileName>
<XPathExpressions>
<Expression>
<XPath>/*[local-name()=āSystemResponseā]/ID</XPath>
<NewValue takeFromCtx="messageID"></NewValue>
</Expression>
</XPathExpressions>
</TestStep>
<!āWait a moment so we donāt copy the file until weāre done updating itā>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.DelayStep">
<Delay>1000</Delay>
</TestStep>
<!āCopy the file to the folder that monitored by the receive location for opicking up system responsesā>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileCreateStep">
<SourcePath>..\..\SystemResponse.xml</SourcePath>
<CreationPath>..\..\SendResponse\SystemResponse.xml</CreationPath>
</TestStep>
</TestExecution>
</TestCase>
</code></pre></div></div>
<p>This might look messy at first but I think itās really cool I also think it worth thinking about on how you should run this at during development otherwise? You would then have to build some small stub to return a response message with the right id ā¦ I prefer this method!</p>
<p>BizUnitExtension makes me like BizUnit even more! Thanks to <a href="http://kevinsmi.blogspot.com/"><em>Kevin. B. Smith</em></a>, <a href="http://santoshbenjamin.wordpress.com/"><em>Santosh Benjamin</em></a> and <em><a href="http://thetaoofbiztalk.blogspot.com/">Gar Mac CrĆostaand</a></em> for spending so much time on this and sharing it with us mere mortals!</p>
<p>Update: Garās blog can be found <a href="http://thetaoofbiztalk.blogspot.com/">here</a>.</p>
How the extend a custom Xslt in BizTalk using EXSLT and the Mvp.Xml project2008-09-05T20:15:55+00:00http://richardhallgren.com/how-the-extend-a-custom-xslt-in-biztalk-using-exslt-and-the-mvpxml-project<p>Lately Iāve been using custom Xslt <a href="http://www.richardhallgren.com/efficient-grouping-and-debatching-of-big-files-using-biztalk-2006/">more</a> and more instead of the BizTalk mapping tool. I still use the mapping tool in easy scenarios when I just need to do some straight mapping or maybe even when I need to concatenate some fields, but as soon as I need to to some looping, grouping, calculations etc Iāve made a <em>promise</em> to myself to use custom Xslt!</p>
<p>I find custom Xslt so much easier in more complex scenarios and once one get past the template matching and understands how and when to use recursion (No you canāt reassign a variable in Xslt and youāre not supposed to!) I find it to be a <strong>dream</strong> compared to the mapping tool. I also find the code so much easier to maintain compared to the result from the mapping tool. I mean someone would have to pay me good money to even start figuring out what <a href="http://www.edsquared.com/content/binary/WindowsLiveWriter/DebugthatBizTalkMap_E215/BadMap_thumb.png">this</a> map is doing. And the scary thing is that if you worked with BizTalk for a while you probably know that maps like this isnāt that rare! Iāve even seen worse!</p>
<p>Donāt get me wrong, Xslt definitely has some <strong>major</strong> <a href="http://biglist.com/lists/xsl-list/archives/200102/msg01384.html">limitations</a>.</p>
<blockquote>Some of the acute limitations of XSLT 1.0 I can think of off the top of my head are:
>
> * The lack of real string comparison
> * No support for dates
> * No simple mechanism for grouping
> * No querying into RTF's
> </blockquote>
<p>And it doesnāt take long before one runs up against one of these and suddenly you wish you were <strong>back</strong> in mapping tool were we just could add scripting functoid and some code or a external assembly. But then you remember ā¦ (Sorry, I know itās painful just to watch it).</p>
<p><a href="../assets/2008/09/windowslivewriterhowtheextendacustomxsltinbizt.xmlproject-138fabadmap-thumb-2.png"><img src="../assets/2008/09/windowslivewriterhowtheextendacustomxsltinbizt.xmlproject-138fabadmap-thumb-thumb.png" alt="BadMap_thumb" /></a></p>
<p>**There has to be a better way of doing this and <em>combining</em> the best out of the two worlds! **</p>
<p>I started looking into to how BizTalk actually solves combining Xslt and the possibility to use external assemblies. After a couple of searches I found Yossiās <a href="http://www.sabratech.co.uk/blogs/yossidahan/archive/2005_08_01_archive.html">nice article</a> that explained it to me (from 2005! Iām behind on this one!) and it even turns out that there an <a href="http://msdn.microsoft.com/en-us/library/ms966408.aspx">example</a> in the BizTalk SDK.</p>
<p>Ok, so now I had what I need. I started a new class library project and began writing some date parsing methods, some padding methods and so on.</p>
<p>It somehow however felt wrong from the start and I got this grinding feeling that I must be reinventing the wheel (I mean these are well know limitations of Xslt and must have been solved before). Even worse I also felt that I was creating a stupid <em>single point of failure</em> as I started using the component from all different maps in my projects and I have actually seen how much pain a bug in similar shared dll:s could cause. Basically <em>a small bug in the component could halt all the process using the library</em>! Finally I realized that this kind of library would be under constant development as we ran into more and more areas of limitations in the our Xslt:s and that would just <strong>increase</strong> the risk of errors and mistakes.</p>
<p>After some further investigation I found <a href="http://www.exslt.org/">EXSLT</a> which looked like a solution to my problems! A <em>stable, tested</em> library of Xslt extensions that we could take dependency on as <strong>itās unlikely to have any bugs and that should include the functionality weāre missing in standard Xslt!</strong></p>
<h3 id="how-i-used-exslt-in-biztalk">How I used EXSLT in BizTalk</h3>
<p>These days itās the <a href="http://www.codeplex.com/MVPXML/People/ProjectPeople.aspx">Xml Mvp crowd</a> over at the <a href="http://www.codeplex.com/MVPXML">Mvp.Xml project</a> who develops and maintains the .NET implementation of EXSLT. So I downloaded the latest <a href="http://www.codeplex.com/MVPXML/Release/ProjectReleases.aspx?ReleaseId=4894">binaries</a> (version 2.3). Put the the <em>Mvp.Xml.dll</em> in the GAC. Wrote a short custom extension Xml snippet that looked like this (using what Iāve learnt from <a href="http://www.sabratech.co.uk/blogs/yossidahan/archive/2005_08_01_archive.html">Yossiās article</a>).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<ExtensionObjects>
<ExtensionObject
Namespace="http://exslt.org/dates-and-times"
AssemblyName="Mvp.Xml,
Version=2.3.0.0, Culture=neutral,
PublicKeyToken=6ead800d778c9b9f"
ClassName="Mvp.Xml.Exslt.ExsltDatesAndTimes"/>
</ExtensionObjects>
</code></pre></div></div>
<p>All you define is the <em>Xml namespace _you like to use in your Xslt to reference the dll, the _full assembly name</em> and finally the <em>name of the class</em> in <em>Mvp.Xml.Exslt</em> you want to use (make sure you also download the source to Xml.Mvp, it helps when looking up in what classes and namespaces different methods are placed).</p>
<p>That means you need one <em>ExtensionObjects</em> block for each class you want you use which really isnāt a problem as the methods are nicely structured based on there functionality.</p>
<p>Then we can use this in a Xslt like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:S1="http://ExtendedMapping.Schema1"
xmlns:S2="http://ExtendedMapping.Schema2"
xmlns:exslt="http://exslt.org/dates-and-times"
version="1.0">
<xsl:template match="/">
<S2:Root>
<Field>
<xsl:value-of select="exslt:dateTime()"/>
</Field>
</S2:Root>
</xsl:template>
</xsl:stylesheet>
</code></pre></div></div>
<p>Which gives us the below output. <strong>Notice the current time and date! Cool!</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><S2:Root xmlns:S1="http://ExtendedMapping.Schema1" xmlns:S2="http://ExtendedMapping.Schema2" xmlns:exslt="http://exslt.org/dates-and-times">
<Field>2008-09-05T20:45:13+02:00</Field>
</S2:Root>
</code></pre></div></div>
<p>All you then have to do in you map is to reference the Xslt and the extension Xml.</p>
<p><a href="../assets/2008/09/windowslivewriterhowtheextendacustomxsltinbizt.xmlproject-138facustom-extension-in-map-2.png"><img src="../assets/2008/09/windowslivewriterhowtheextendacustomxsltinbizt.xmlproject-138facustom-extension-in-map-thumb.png" alt="Custom Extension In Map" /></a></p>
<p>Just as final teaser Iāll paste a few methods from the <a href="http://www.exslt.org/">EXSLT documentation</a></p>
<p>Some <em>string</em> methods:</p>
<ul>
<li>
<p>str:align()</p>
</li>
<li>
<p>str:concat()</p>
</li>
<li>
<p>str:decode-uri()</p>
</li>
<li>
<p>str:encode-uri()</p>
</li>
<li>
<p>str:padding()</p>
</li>
<li>
<p>str:replace()</p>
</li>
<li>
<p>str:split()</p>
</li>
<li>
<p>str:tokenize()</p>
</li>
</ul>
<p>Some <em>date and time</em> methods:</p>
<ul>
<li>
<p>date:add()</p>
</li>
<li>
<p>date:add-duration()</p>
</li>
<li>
<p>date:date()</p>
</li>
<li>
<p>date:date-time()</p>
</li>
<li>
<p>date:day-abbreviation()</p>
</li>
<li>
<p>date:day-in-month()</p>
</li>
<li>
<p>date:day-in-week()</p>
</li>
<li>
<p>date:day-in-year()</p>
</li>
<li>
<p>date:day-name()</p>
</li>
<li>
<p>date:day-of-week-in-month()</p>
</li>
<li>
<p>date:difference()</p>
</li>
<li>
<p>date:duration()</p>
</li>
<li>
<p>date:format-date()</p>
</li>
<li>
<p>date:hour-in-day()</p>
</li>
<li>
<p>date:leap-year()</p>
</li>
<li>
<p>date:minute-in-hour()</p>
</li>
<li>
<p>date:month-abbreviation()</p>
</li>
<li>
<p>date:month-in-year()</p>
</li>
<li>
<p>date:month-name()</p>
</li>
<li>
<p>date:parse-date()</p>
</li>
<li>
<p>date:second-in-minute()</p>
</li>
<li>
<p>date:seconds()</p>
</li>
<li>
<p>date:sum()</p>
</li>
<li>
<p>date:time()</p>
</li>
<li>
<p>date:week-in-month()</p>
</li>
<li>
<p>date:week-in-year()</p>
</li>
<li>
<p>date:year()</p>
</li>
</ul>
<p>As if this was enough (!) the Mvp Xml project added a couple of there own methods! What about <strong><em>string lowercase</em></strong> and <strong>_string uppercase - _all in Xslt!</strong> And about 30 new date-time related methods extra to the standard ones already in EXSLT!</p>
<p>Check out the full documentation <a href="http://www.xmllab.net/mvpxml/default.aspx">here</a>!</p>
<p>Let me know how it works out for you.</p>
Efficient grouping and debatching of big files using BizTalk 20062008-07-16T10:06:06+00:00http://richardhallgren.com/efficient-grouping-and-debatching-of-big-files-using-biztalk-2006<p>Iāve seen people struggle both on the <a href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3564558&SiteID=1">forums</a> and while doing consulting when in it comes to finding an good way of grouping and transforming content in file before debatching it. Say for example we have a text file like the example below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0001;Test row, id 0001, category 10;10
0002;Test row, id 0002, category 10;10
0003;Test row, id 0003, category 10;10
0004;Test row, id 0004, category 20;20
0005;Test row, id 0005, category 20;20
0006;Test row, id 0006, category 20;20
0007;Test row, id 0007, category 20;20
0008;Test row, id 0008, category 10;10
0009;Test row, id 0009, category 10;10
0010;Test row, id 0010, category 30;30
</code></pre></div></div>
<p>Notice how the the ten rows belong to three different categories (10,20 and 30). These kind of export are in my experience quite common batch export from legacy systems and they usually arenāt ten rows (in my last project the sizes ranged from 5 MB to 25 MB) ā¦</p>
<h3 id="the-problem">The problem</h3>
<p>The problem is that the receiving system expects the data to be in <em>separate groups,</em> <em>grouped by the categories the rows belong to</em>. The expected message might look something like the below for category 10 (notice how all rows within the group are from category 10)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ns1:Group numberOfRows="5" xmlns:ns1="http://Blah/Group">
<Row>
<Id>0001</Id>
<Text>Test row, id 0001, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<Id>0002</Id>
<Text>Test row, id 0002, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<Id>0003</Id>
<Text>Test row, id 0003, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<Id>0008</Id>
<Text>Test row, id 0008, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<Id>0009</Id>
<Text>Test row, id 0009, category 10</Text>
<Category>10</Category>
</Row>
</ns1:Group>
</code></pre></div></div>
<p>The problem is now that we need to find a efficient way of first <em>grouping the incoming flat file based message</em> and then to _debatch it using those groups. <strong>Our ultimate goal is to have separate messages that groups all rows that belongs to the same category and then send these messages to the receiving system</strong>. _How would you solve this?</p>
<p>Iāve seen loads of different solution involving orchestrations, databases etc, but the main problem they all had in common is that theyāve loaded up to much of the message in memory and finally hit an <em>OutOfMemoryException</em>.</p>
<h3 id="the-solution">The solution</h3>
<p>The way to solve this is to use pure messaging as one of the new features in BizTalk 2006 is the new <a href="http://www.microsoft.com/technet/prodtechnol/biztalk/2006/evaluate/overview/default.mspx">large messages transformation engine</a>.</p>
<blockquote>
>
> **Large message transformation.** In previous versions of BizTalk Server, mapping of documents always occurred in-memory. While in-memory mapping provides the best performance, it can quickly consume resources when large documents are mapped. In BizTalk Server 2006, large messages will be mapped by the new large message transformation engine, which buffers message data to the file system, keeping the memory consumption flat.
>
>
</blockquote>
<p>So the idea is the to read the incoming flat file, use the <a href="FlatFileDisassembler">Flat File Disassembler</a> to transform the message to itās XML representation (step 1,2 and in the figure below) and the to use XSLT to transform in to groups (step 4 and 5). We will then use the <a href="http://msdn.microsoft.com/en-us/library/aa561814.aspx">XML Disassembler</a> to split those groups into separate messages containing all the rows within a category (step 6 and 7).</p>
<p><a href="../assets/2008/07/windowslivewriterefficientgroupingandsplittingofbigfiles-8295groupingflow2-2.png"><img src="../assets/2008/07/windowslivewriterefficientgroupingandsplittingofbigfiles-8295groupingflow2-thumb.png" alt="GroupingFlow2" /></a></p>
<p>Step 1, 2 and 3 are <a href="http://msdn.microsoft.com/en-us/library/aa577898.aspx">straight forward</a> and pure configuration. Step 4 and 5 will require some custom XSLT and Iāll describe that in more detail in the section below. Step 6 and 7 will be discussed in the last section of the post.</p>
<h4 id="grouping">Grouping</h4>
<p>Letās start by looking at a way to group the message. I will use some custom XSLT and a technique called the <a href="http://www.jenitennison.com/xslt/grouping/muenchian.html">Muenchian method</a>. A segment from the XML representation of the flat file message could look something like this.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><Rows xmlns="http://Blah/Incoming_FF">
<Row xmlns="">
<ID>0001</ID>
<Text>Test row, id 0001, category 10</Text>
<Category>10</Category>
</Row>
<Row xmlns="">
<ID>0002</ID>
<Text>Test row, id 0002, category 10</Text>
<Category>10</Category>
</Row>
...
[message cut for readability]
</code></pre></div></div>
<p>The XSLT will use could look something like the below. Itās kind of straight forward and Iāve tried commenting the important parts of in the actual script. Basically it will use keys to fins the unique categories and then (again using keys) selecting those rows within the category to loop and write to a group.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="http://GroupAndDebatch.Schemas.Incoming_FF"
xmlns:ns2="http://GroupAndDebatch.Schemas.Grouped"
>
<!--Defining the key we're gonna use-->
<xsl:key name="rows-by-category" match="Row" use="Category" />
<xsl:template match="/ns1:Rows">
<ns2:Groups>
<!--Looping the unique categories to get a group for-->
<xsl:for-each select="Row[count(. | key('rows-by-category', Category)[1]) = 1]">
<!--Creating a new group and set the numberOfRows-->
<Group numberOfRows="{count(key('rows-by-category', Category))}">
<!--Loop all the rows within the specific category we're on-->
<xsl:for-each select="key('rows-by-category', Category)">
<Row>
<ID>
<xsl:value-of select="ID"/>
</ID>
<Text>
<xsl:value-of select="Text"/>
</Text>
<Category>
<xsl:value-of select="Category"/>
</Category>
</Row>
</xsl:for-each>
</Group>
</xsl:for-each>
</ns2:Groups>
</xsl:template>
</xsl:stylesheet>
</code></pre></div></div>
<blockquote>
>
> [![note](../assets/2008/07/windowslivewriterefficientgroupingandsplittingofbigfiles-8295note-thumb.gif)](../assets/2008/07/windowslivewriterefficientgroupingandsplittingofbigfiles-8295note-2.gif)You have found all the [XSLT and XML related features](http://msdn.microsoft.com/en-us/library/aa302298.aspx) in Visual Studio - right?
>
>
</blockquote>
<p>Ok, so the above XSLT will give us a XML structure that looks some like this.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<ns2:Groups xmlns:ns2="http://Blah/Groups" xmlns:ns1="http://Blah/Group">
<ns1:Group numberOfRows="5">
<Row>
<ID>0001</ID>
<Text>Test row, id 0001, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<ID>0002</ID>
<Text>Test row, id 0002, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<ID>0003</ID>
<Text>Test row, id 0003, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<ID>0008</ID>
<Text>Test row, id 0008, category 10</Text>
<Category>10</Category>
</Row>
<Row>
<ID>0009</ID>
<Text>Test row, id 0009, category 10</Text>
<Category>10</Category>
</Row>
</ns1:Group>
<ns1:Group numberOfRows="4">
<Row>
<ID>0004</ID>
<Text>Test row, id 0004, category 20</Text>
<Category>20</Category>
</Row>
...
[message cut for readability]
</code></pre></div></div>
<p><strong>Finally! This we can debatch!</strong></p>
<h4 id="debatching">Debatching</h4>
<p>Debatch the <em>Groups</em> message above is also rather straight forward and I wonāt spend much time on in this post. The best way to learn more about it is to have a look ate the <a href="http://msdn.microsoft.com/en-us/library/ms966332.aspx">EnvelopeProcessing sample</a> in the BizTalk SDK.</p>
<p><strong>And the end result of the debatching are single messages within a unique category, just as the receiving system expects! Problem solved.</strong></p>
<h3 id="issue-1---slow-transformations">Issue #1 - slow transformations</h3>
<p>The first time Iāve put a solution like this in test and started testing with some real sized messages (> 1 MB) I really panicked, the mapping took forever. And I really mean forever, I sat there waiting for 2-3 hours (!) for a single file getting transformed. When I had tested the same XML based file in Visual Studio the transformation took about 10 seconds so I knew that wasnāt it. With some digging <a href="http://technet.microsoft.com/en-us/library/aa560481.aspx">here</a> I found the <em>TransformThreshold</em> parameter.</p>
<p><em>TransformThreshold</em> decides how big a message can be in memory before BizTalk start buffering it to disk. The default value is 1 MB and one really has to be careful when changing this. Make sure you thought hard about your solution and situation before changing the value - how much traffic do you receive and how much of that can you afford reading in to memory?</p>
<p>In my case I received a couple of big files spread out over a night so setting parameter with a large amount wasnāt really a problem and that really solved the problem. The mapping finished in below 10 minutes as I now allow a much bigger message to be read into memory and executed in memory before switching over to the large message transformation engine and start buffering to disk (which is always much slower).</p>
<h3 id="problem-2---forced-to-temp-storage">Problem #2 - forced to temp storage</h3>
<p>Looking at the model of the data flow again you probably see that Iām using the XML Disassembler to split the grouped files (step 5 to step 6).</p>
<p><a href="../assets/2008/07/windowslivewriterefficientgroupingandsplittingofbigfiles-8295groupingflow3-2.png"><img src="../assets/2008/07/windowslivewriterefficientgroupingandsplittingofbigfiles-8295groupingflow3-thumb.png" alt="GroupingFlow3" /></a></p>
<p>The only way Iāve found this to work is actually to write the Grouped XML message to file and the to read that file in to BizTalk again and in that receive pipeline debatch the message. Not the most elegant solution, but there really isnāt a another out-of-the-box way of debatching messages (the XML Assembler canāt do it) and I donāt want to use an orchestration to execute the a pipeline as I want to keep the solution pure messaging for simplicity and performance reasons.</p>
<h3 id="finishing-up">Finishing up</h3>
<p>Have you solved similar cases differently? Iād be very interested in your experience! I also have a sample solution of this - just send me an <a href="email:richard.hallgren@gmail.com">email</a> and make sure youāll get it.</p>
<h3 id="update">Update</h3>
<p>Also donāt miss <a href="http://biztalkhotrod.com/Documents/BizTalk_HotRod_Issue6_Q2_2009.pdf">this issue</a> (pdf) of <a href="http://biztalkhotrod.com/">BizTalk Hotrod magazine</a>. There is an article on āMuenchian Grouping and Sorting using Xsltā describing exactly the problem discussed above.</p>
Running MSBuild scripts from Visual Studio2008-07-09T09:04:22+00:00http://richardhallgren.com/running-msbuild-scripts-from-visual-studio<p><a href="../assets/2008/07/windowslivewriterrunningmsbuildscriptsfromvisualstudio-9bb0msbuild2-2.png"><img src="../assets/2008/07/windowslivewriterrunningmsbuildscriptsfromvisualstudio-9bb0msbuild2-thumb.png" alt="MSBuild2" /></a>It seems like there more build script one writes, the more often one wants to run them and itās always a bit annoying (and time consuming) having to leave Visual Studio and start MSBuild from the command line. Brennan Stehling has a cool solution to that problem <a href="http://brennan.offwhite.net/blog/2007/05/31/running-msbuild-from-visual-studio/">here</a> were he sets up MSBuild as an external tool and runs it.</p>
<p>One problem for us was the we had our solution files in one place on the file system and our build files in a totally different place. The solution was to add the build file for the current solution as a <a href="http://msdn.microsoft.com/en-us/library/haytww03(VS.80).aspx">Solution Folder</a> (as shown in the figure below) and then set MSBuild to use $(ItemDir) as its Initial Directory. That will kick of MSBuild from the directory that the current selected Solution Folder points to and in our case thatās were the XXX.Build.Article.proj file exists.</p>
<p><a href="../assets/2008/07/windowslivewriterrunningmsbuildscriptsfromvisualstudio-9bb0msbuild-6.png"><img src="../assets/2008/07/windowslivewriterrunningmsbuildscriptsfromvisualstudio-9bb0msbuild-thumb-2.png" alt="MSBuild" /></a></p>
Looking forward to stackoverflow.com2008-07-09T06:52:12+00:00http://richardhallgren.com/looking-forward-to-stackoverflowcom<p><a href="../assets/2008/07/windowslivewriterlookingforwardtostackoverflow.com-7cb8stackoverflow-logo-250-2.png"><img src="../assets/2008/07/windowslivewriterlookingforwardtostackoverflow.com-7cb8stackoverflow-logo-250-thumb.png" alt="stackoverflow-logo-250" /></a>Iām really looking forward to the release of s<a href="http://stackoverflow.com/">tackoverflow.com</a> - have you heard about it? If not itās a collaboration between <a href="http://www.joelonsoftware.com/AboutMe.html">Joel Spolsky</a> and <a href="http://www.codinghorror.com/blog/archives/000021.html">Jeff Atwood</a>. Joel and Jeff are of course the two blogger behind the popular <a href="http://www.joelonsoftware.com/">Joel on Software</a> and <a href="http://www.codinghorror.com/blog/">Coding Horror</a> blogs.</p>
<p>Joel is also one of the founders of the <a href="http://fogcreek.com/">FogCreek Software</a> company. FogCreek has a couple of different products but the most known is probably <a href="http://fogcreek.com/FogBugz/">FogBugz</a> which is a really cool project management/bug tracking/wiki/support tool for software development and management. At first it might not look like a very impressing tool but have a look at <a href="http://www.joelonsoftware.com/items/2007/10/24austindemo.html">this presentation</a> by Joel and I think youāll start thinking different (I know we did and weāre now using it for both planing and managing big integrations projects).</p>
<p>Anyway, if you missed the story behind stackoverflow have a look <a href="http://blog.stackoverflow.com/">here</a> and donāt miss the <a href="http://blog.stackoverflow.com/index.php?feed=podcast">podcasts</a> that Joel and Jeff record, some of them are really cool. I know Iāve learnt a lot by just listening in to their conversations.</p>
<p>We not have quite a few online BizTalk communities such as <a href="http://forums.microsoft.com/msdn/default.aspx?ForumGroupID=398&SiteID=1">the Microsoft forums</a>, <a href="http://groups.google.com/group/microsoft.public.biztalk.general/topics">Google Groups</a>, <a href="http://www.biztalkgurus.com/forums/default.aspx">BizTalk Gurus</a>, <a href="http://www.facebook.com/">facebook</a> (search for BizTalk related groups) and at <a href="https://www.linkedin.com/home">LinkedIn</a> (a couple of open BizTalk related groups) - is there room for another one at stackoverflow? Do we need one?</p>
Removing XML namespaces - revisit2008-06-26T07:25:33+00:00http://richardhallgren.com/removing-xml-namespaces-revisit<p>I have a <a href="http://www.richardhallgren.com/removing-namespace-from-outgoing-messages/">old post on removing XML namespace</a> from outgoing messages using XSLT in a map on the send port. Removing XML namespace is usually a late requirement that shows up during integration tests with for example legacy systems that has problems reading XML and only finds XML namespaces messy and confusing and wants it removed.</p>
<p>The post recently got commented by <a href="http://codebetter.com/blogs/jeff.lynch/">Jeff Lynch</a> (one of the <a href="http://codebetter.com/">codebetter.com</a> bloggers) asking me why I just didnāt create a schema without any XML namespace in it to represent the outgoing schema (see figure below) and then map to that in the send port.</p>
<p><a href="../assets/2008/06/windowslivewriterremovingxmlnamespacesrevisit-834dremoving-xml-namespaces-revisit-2.png"><img src="../assets/2008/06/windowslivewriterremovingxmlnamespacesrevisit-834dremoving-xml-namespaces-revisit-thumb.png" alt="Removing XML namespaces - revisit" /></a></p>
<p>Say for example that we have incoming messages like the one below with namespaces.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">ns0:BlahRoot </span><span style="color: #FF0000; ">xmlns:ns0</span><span style="color: #0000FF; ">="http://Sample.BlahIncomingSchema"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">BlahNode</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">Test Value</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">BlahNode</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ns0:BlahRoot</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>Weāve then defined a schema without namespace and map to that and get the following result.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">BlahRoot</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">BlahNode</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">Test Value</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">BlahNode</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">BlahRoot</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>This method is of course much cleaner then any previous and itās also more conceptually correct as the schema actually represents the contact between BizTalk and the receiving system (the contract is a message without namespace in it, <strong>not one with that we then remove</strong>).</p>
<p>The only problem with this kind of approach is that as BizTalk recognized the message type using a combination between root node and XML namespace we canāt have another schema with the <em>BlahRoot</em> root node without a defined XML namespace. Even if those two schemas would look totally different in structure and be two different message types BizTalk would be able to see the difference (to BizTalk they both be <em>#BlahRoot</em> message types).</p>
<p>Thanks Jeff for pointing this out to me.</p>
Does BizTalk have man-boobs?2008-06-09T07:14:04+00:00http://richardhallgren.com/does-biztalk-have-man-bobs<p>Iāve just finished watching <a href="http://www.infoq.com/presentations/soa-without-esb">this webcast</a> from <a href="http://qcon.infoq.com/sanfrancisco-2008/conference/">QCon 2008</a> with <a href="http://martinfowler.com/">Martin Fowler</a> and <a href="http://jim.webber.name/">Jim Webber</a>. Itās basically their view on how integration middleware is used today and how we plan and implement our SOA and ESB project.</p>
<p>Their main point is that we use much to bloated middleware (BizTalk is mentioned as an example here) and that we should have a more agile approach to implement SOA and ESBs. Theyāve used all the agile ideas (testing, isolated testable functionality, deliver small and often, continuous builds etc, etc) and applied them to integration - fair enough. I totally agree that trying to convert your complete enterprise architecture into a SOA architecture is a guaranteed failure. This is also <a href="http://www.microsoft.com/biztalk/solutions/soa/overview.mspx#EZB">something we heard for a while now from others</a> as well.</p>
<p>I do also agree that BizTalk is a huge platform and that it isnāt perfect in all aspects. IMHO it does however give us some important advantages compared to a custom coded message bus and services. Iāll try and list a few of them below.</p>
<ol>
<li><strong>Fixed architecture</strong> <br />
We donāt have invent the wheel every time. BizTalk is a product with an <a href="http://msdn.microsoft.com/en-us/library/aa561521.aspx">architecture</a> that one have to learn and use. There are times when this is a pain (did I hear low latency and BizTalk persistence points?) but itās also a huge kick start to all projects once you learnt it. Once you figured out how you use the products youāll actually have something up and running in no time.</li>
</ol>
<p>Isnāt an early delivery that we can test something good? Iām sure I can deliver a BizTalk based integration faster that some can using custom code when starting from scratch.</p>
<ol>
<li><strong>Drag-and-drop</strong> <br />
There is a learning curve to BizTalk and all itās tools but once one gotten over this one can move really fast, even without a deep understanding of .NET and software development (there are of course both pros and cons to this). Iāve seen projects with 50+ integration processes (to me thatās a big, complex project) where we actually used people fresh out of school, spent two weeks to teach them basic BizTalk and had them deliver critical parts of the projects. Iād like to see that happen custom coded ESB project with thousands lines of code ā¦</li>
</ol>
<p>You probably get a nice design and implementation if you can hire 10 top developers and a couple of architects, but that isnāt always possible.</p>
<ol>
<li>
<p><strong>Tools <br />
**Does a custom code, lean approach, really scale in this scenario? Do you take the time to pause and build that management and configuration tool that you donāt get with a custom code project? I donāt say that we got the perfect view and control of our processes and messages in BizTalk but at least we got **some</strong> control. At least I got the <a href="http://technet.microsoft.com/en-us/library/aa578089.aspx">BizTalk Administration Console</a> to let me see how my different application are doing, what messages and process etc that got suspended. At least I got the BAM framework where I can configure a tracking and monitoring in no time (usually ā¦) etc, etc.</p>
</li>
<li>
<p>**It works <br />
**Say your implementing a process that receives purchase orders and that these orders might contain orders for a couple of millions dollars. Do you want to be developer that tells you boss that you think you might have lost a message due to a exception in your custom code? Of course you have 90% test coverage and continuous integration but you never tested for this exception case ā¦ I donāt want to be that developer/architect.</p>
</li>
</ol>
<p>I donāt say donāt test. Iām very pro testing and I really feel that agile is the right approach. Iām just saying I need something tested and safe to build this super critical solutions on. Something that I know works and that I can be really productive on and start solving business cases from minute one.</p>
<p>What do you think? Does BizTalk have man-bobs and is that only a bad thing? And does Martin Fowler really have leather pants on?</p>
Speaking at KNUG - Karlstad .NET User Group2008-05-09T14:05:53+00:00http://richardhallgren.com/speaking-at-knug-karlstad-net-user-group<p>Yesterday I presented the <a href="http://www.richardhallgren.com/talking-at-developer-summit-on-masterdata-management-using-biztalk-2006/">MasterData Management using BizTalk 2006 R2 talk</a> (Iāll soon have a post out with the presentation in English) I recently held at Developer Summit at the local .NET user group in Karlstad (<a href="http://www.compare.se/index.asp?id=6221">KNUG</a>).</p>
<p><a href="../assets/2008/05/windowslivewriterspeakingatknugkarlstad.netusergroup-e257janolof-on-how-to-be-cool.jpg"><img src="../assets/2008/05/windowslivewriterspeakingatknugkarlstad.netusergroup-e257janolof-on-how-to-be-cool-thumb.jpg" alt="Janolof on how to be cool" /></a>KNUG is a new .NET user group that I actually helped start a couple of months ago. This meeting was the second meeting for the group. The meeting was attended by about 20 persons and we had two presentations on the agenda. Besides my own Thomas Heder showed the group some <a href="http://en.wikipedia.org/wiki/Language_Integrated_Query">LINQ</a> and how he and his colleagues uses <a href="http://www.linqpad.net/">LINQPad</a> to develop and test there queries.</p>
<p>We also discussed future subjects, possible speakers and moving information on the group over to a <a href="http://communityserver.com/">Community Server</a> driven site.</p>
<p>Does anyone have any experience on Community Server and how the feature set matches those need for running a user group (managing users, blogs, email lists, calendar etc)?</p>
Using BAM for latency tracking in a BizTalk request response scenario2008-04-28T13:35:15+00:00http://richardhallgren.com/using-bam-for-latency-tracking-in-a-biztalk-request-response-scenario<p>This post will try and explain how BAM tracking can be used in SOAP based request response scenario in BizTalk 2006. It important to notice that some of the issues discussed in the post are specific to the SOAP adapter and are non-issues if the scenario would for example use the the WCF adapter or similar.</p>
<h3 id="describing-the-scenario">Describing the scenario</h3>
<p>In this case we have a SOAP receive port that receives a request and returns a response. The request is routed to a orchestration that calls three different send ports. These ports then sends new requests to back-end systems and returns responses (communication with back-ends systems are also SOAP based). The three responses are used to build up the final response that is then returned to original receive port as a final response.</p>
<p>Our goal is to track the duration between the request and response on each of the ports. The idea is also to find a solution and tracking model that doesnāt have to change if we add or remove ports or add similar processes to track.</p>
<h4><a href="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bscenario-2.jpg"><img src="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bscenario-thumb.jpg" alt="scenario" /></a></h4>
<h4 id="defining-and-deploying-the-tracking-model">Defining and deploying the tracking model</h4>
<p>Weāll start by defining our tracking model in Excel. Our activity contains of the following items:</p>
<ul>
<li>
<p><strong>InterchangeId</strong> (data item) <br />
As we wonāt correlate all the tracking point into one single row (that would break the goal of having one model for all processes, the model would then have to be specific for one process and itās specific ports) the interchange id will then tell us what different rows belong together and that describes one process.</p>
</li>
<li>
<p><strong>ReceivePortName</strong> (data item) <br />
The name of the receive port.</p>
</li>
<li>
<p><strong>Request</strong> (milestone item) <br />
The time the request was either sent or received (depending on if we track a port that received/sent the request using a receive port or send port).</p>
</li>
<li>
<p><strong>Response</strong> (milestone item) <br />
The time the response was either sent or received (depending on if we track a port that received/sent itās response on a receive port or send port).</p>
</li>
<li>
<p><strong>SendPortName</strong> (data item) <br />
The name of the send port.</p>
</li>
</ul>
<p>After we described the model itās time to export it to an XML representation and then to use the <a href="http://technet.microsoft.com/en-us/library/aa547898.aspx">BM tool</a> to deploy it and generate the BAM database infrastructure. Youāll find some nice info on this <a href="http://msdn2.microsoft.com/en-us/library/aa558802.aspx">here</a>.</p>
<h3 id="using-the-tracking-profile-editor-to-bind-the-model">Using the Tracking Profile Editor to bind the model</h3>
<p>Next step is to bind the model to the implementation using the <a href="http://msdn2.microsoft.com/en-us/library/ms946851.aspx">Tracking Profile Editor</a>. The figure below shows the different properties that were used. Notice that none of the items was bound to the actual orchestration context. All properties are general properties that we track <strong>on the ports</strong>.** **This is important as that gives us the possibility to just add and remove ports to change the tracking.</p>
<p>**<a href="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0btracking-profile-using-continuation-2.jpg"><img src="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0btracking-profile-using-continuation-thumb.jpg" alt="tracking profile using continuation" /></a> **</p>
<hr />
<p>The next figure shows how the tracking of the request milestone event actually happens on either the RP1 port or on any of the three different send ports! If we developed a new process using other ports we could just add it here, no new model required.</p>
<p><a href="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0btracking-profile-configure-ports-2-4.jpg"><img src="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0btracking-profile-configure-ports-2-thumb-1.jpg" alt="tracking profile configure ports 2" /></a></p>
<h3 id="what-about-the-continuation-then">What about the continuation then?</h3>
<p>Our final problem is that unless we somehow correlate our request tracking point with our receive tracking point the receive weāll end up with each tracking point spread over several different rows. In the example below Iāve marked the request for the RP01 port and the response event on the same port.</p>
<p><a href="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bbam-portal-split-results-4.jpg"><img src="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bbam-portal-split-results-thumb-1.jpg" alt="bam portal split results" /></a></p>
<p>The reason for this is of course that BAM doesnāt have a context for the two tracking points and doesnāt know that actually belongs together. This differs from tracking in a orchestration were we always are in a context (the context of the orchestration), itās then easy for BAM to understand that we like to view all the tracking point as one row ā when tracking on ports itās different. Continuation helps us tell BAM that we like have a context and correlate these two points.</p>
<p><a href="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0btracking-profile-using-continuation-2-6.jpg"><img src="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0btracking-profile-using-continuation-2-thumb-2.jpg" alt="tracking profile using continuation 2" /></a></p>
<p>In our case ServiceID is the prefect candidate for correlating the two points. A request and a response will have the same service id. In an other situation we could just as well have used a value from inside the message (say for example an invoice id).</p>
<p><strong>The result is one single row for the request response for each port</strong>. So in our case a complete process (a complete interchange) is shown on four rows (one row for each of the ports). In the example below the first rows shows us the complete duration (and the other tracking data) between the request response to the client. The other rows show the duration for the send ports communication with the back-ends systems.</p>
<p><a href="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bbam-portal-complete-results-2.jpg"><img src="../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bbam-portal-complete-results-thumb.jpg" alt="bam portal complete results" /></a></p>
<p>This model might not be optimal in an other scenario where your process are more fixed and you can then create a tracking model that is more specific to you actual process. But this solution meets our design goal as weāre now able to just add and remove port using the tracking profiler to track new port in completely new processes without having to go back and change the tracking model.</p>
<blockquote>
>
> [![note](../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bnote-thumb.gif)](../assets/2008/04/windowslivewriterusingbamforlatencytrackinginabiztalkrequ-9c0bnote-2.gif) NOTE: When configuring BAM to track a port the _[MessageType](http://msdn2.microsoft.com/en-us/library/aa561650.aspx)_ is actually promoted. This causes some problems in combination with the SOAP based ports that have been published using the Web Services Publishing Wizard. Saravana writes about this [here](http://www.digitaldeposit.net/blog/2007/08/soap-adapter-and-biztalk-web-publishing.html) and all his articles on this subject is a must read when working with SOAP ports. The problem however comes down to that the Web Services Publishing Wizard generates code that puts the wrong _DocumentSpecName _in the message context and that causes the _XmlDisassembler_ to fail (it tricks the _XmlDisassembler_ to look for a _MessageType_ that doesn't exists).
>
>
>
> This usually isnāt a problem (unless you like to use a map on a port) but as BAM will force the port to promote the _MessageType_ based on the _DocumentSpecName _weāll have to fix this. Saravana has two solutions to the problem and I find the one that replaces the _DocumentSpecName_ with a null value and lets the _XmlDisassembler_ find the _MessageType_ to work well.
>
> </blockquote>
Speaking at Developer Summit on Masterdata Management using BizTalk 20062008-04-24T20:33:39+00:00http://richardhallgren.com/talking-at-developer-summit-on-masterdata-management-using-biztalk-2006<p>I recently spoke at the leading developer conference here in Sweden called <a href="http://www.expertzone.se/dev08/">Developer Summit</a>. The talk was called <em>Masterdata Management using BizTalk 2006</em>. The slides can be found <a href="http://www.richardhallgren.com/blogfiles/MasterData%20Management%20-%20Developer%20Summit%203.0.ppt">here</a>.</p>
<p>I can really recommend Developer Summit as a conference. Everything is super well organized and having the opportunity to listen to celebrities like <a href="http://www.davidchappell.com/blog/">David Chappell</a>, <a href="http://jim.webber.name/">Jim Webber</a>, <a href="http://dannorth.net/">Dan North</a> and <a href="http://blogs.thinktecture.com/cweyer/">Christian Weyer</a> <strong>in Sweden</strong> is really great!</p>
<p>This year I also liked the mix of presentation as some where more general presentation as for example Benjamin Ling whoās the director of platform at Facebook and who gave an insight to how the platform is managed and developed. I also really enjoyed (besides the obvious ones as for example Christian Weyerās WCF talk) Frans Hanelās talk on the history and architecture behind a major price comparison site called <a href="http://prisjakt.nu/">prisjakt.nu</a> - very interesting and a great technical mix in otherwise Microsoft focused conference.</p>
Writing BizTalk context properties to a message from a WCF service using behaviors2008-04-24T17:43:28+00:00http://richardhallgren.com/writing-biztalk-context-properties-to-a-message-from-a-wcf-service-using-behaviors<p>The new WCF adapter in BizTalk 2006 R2 offers a lot of new possibilities. One of those is to write data to the BizTalk Message context properties directly from an exposed WCF Service. A practical use of this technic could be to write the username from the Windows credentials of the calling client into the context of the BizTalk message. This could be useful as this information is encrypted in messages that are received via the WCF adapter and isnāt possible to read when inside BizTalk. Iāll try and demonstrate the technique in this post.</p>
<p>If you have used the SOAP adapter before you might know that all you had to do was to turn on Windows based security for the exposed SOAP service and the username was automatically promoted to the context of the incoming BizTalk message. That username could then be used for routing, tracking which user called the service or using the value in plain text when communicating further to other connected systems. However using the WCF adapter this is not true anymore - when using the new <a href="http://msdn2.microsoft.com/en-us/library/ms789036.aspx">WCF Message Security model</a> the username and password is encrypted in the message and once the message is received by BizTalk itās to late to read it. Basically we have to read the username in the actual service and write it into our own context property (that doesnāt get encrypted).</p>
<p>One way of achieving this is to read the username in the service and then to add it to the WCF Message Headers. All WCF message headers will by default be written to a the BizTalk Message context property called <a href="http://msdn2.microsoft.com/en-us/library/bb259987.aspx">InboundHeaders</a> (in the <em>http://schemas.microsoft.com/BizTalk/2006/1/Adapters/WCF-properties</em> namespace). First weāll create an EndpointBehavior that will use a MessageInspector to add the username to the message header. Finally we create BehaviorExtensionElement so we can use a WCF Custom Binding in BizTalk and configure it to add our new behavior.</p>
<h3 id="creating-the-new-endpointbehavior">Creating the new EndpointBehavior</h3>
<p>To create the configurable behavior weāll need the three classes we mentioned above.</p>
<ol>
<li>
<p>A class that implements the <a href="http://msdn2.microsoft.com/en-us/library/system.servicemodel.dispatcher.idispatchmessageinspector.aspx">IDispatchMessageInspector</a> interface to handle to reading and writing to the actual message.</p>
</li>
<li>
<p>A class that implements the <a href="http://msdn2.microsoft.com/en-us/library/system.servicemodel.description.iendpointbehavior.aspx">IEndpointBehavior</a> interface to define what kind of endpoint weāre creating and what it should do.</p>
</li>
<li>
<p>A class that implements the <a href="http://msdn2.microsoft.com/en-us/library/system.servicemodel.configuration.behaviorextensionelement.aspx">BehaviorExtensionElement</a> abstract class to create the behavior and make it configurable.</p>
</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000ff">using</span><span style="color: #000000"> System;
</span><span style="color: #0000ff">using</span><span style="color: #000000"> System.Collections.Generic;
</span><span style="color: #0000ff">using</span><span style="color: #000000"> System.Text;
</span><span style="color: #0000ff">using</span><span style="color: #000000"> System.ServiceModel;
</span><span style="color: #0000ff">using</span><span style="color: #000000"> System.ServiceModel.Channels;
</span><span style="color: #0000ff">using</span><span style="color: #000000"> System.ServiceModel.Dispatcher;
</span><span style="color: #0000ff">using</span><span style="color: #000000"> System.ServiceModel.Description;
</span><span style="color: #0000ff">using</span><span style="color: #000000"> System.ServiceModel.Configuration;
</span><span style="color: #0000ff">namespace</span><span style="color: #000000"> CustomWCFProperties.Behavior
{
</span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><summary></span><span style="color: #008000">
</span><span style="color: #808080">///</span><span style="color: #008000"> PromoteUserNameMessageInspector implements IDispatchMessageInspector and adds the name from the WindowsIdentity to a WCF header called WindowsUserName in the </span><span style="color: #008000; text-decoration: underline">http://CustomWCFProperties.Schema</span><span style="color: #008000"> namespace. BeforeSendReply only returns as we're not interested in handling the response.
</span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"></summary></span><span style="color: #808080">
</span><span style="color: #000000"> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">class</span><span style="color: #000000"> PromoteUserNameMessageInspector : IDispatchMessageInspector
{
</span><span style="color: #0000ff">#region</span><span style="color: #000000"> IDispatchMessageInspector Members</span><span style="color: #000000">
</span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">object</span><span style="color: #000000"> AfterReceiveRequest(</span><span style="color: #0000ff">ref</span><span style="color: #000000"> System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
</span><span style="color: #0000ff">string</span><span style="color: #000000"> windowsUserName </span><span style="color: #000000">=</span><span style="color: #000000"> ServiceSecurityContext.Current.WindowsIdentity.Name;
request.Headers.Add(MessageHeader.CreateHeader(</span><span style="color: #000000">"</span><span style="color: #000000">WindowsUserName</span><span style="color: #000000">"</span><span style="color: #000000">, </span><span style="color: #000000">"</span><span style="color: #000000">http://CustomWCFProperties.Schema</span><span style="color: #000000">"</span><span style="color: #000000">, windowsUserName));
</span><span style="color: #0000ff">return</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">;
}
</span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> BeforeSendReply(</span><span style="color: #0000ff">ref</span><span style="color: #000000"> Message reply, </span><span style="color: #0000ff">object</span><span style="color: #000000"> correlationState)
{
</span><span style="color: #0000ff">return</span><span style="color: #000000">;
}
</span><span style="color: #0000ff">#endregion</span><span style="color: #000000">
}
</span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><summary></span><span style="color: #008000">
</span><span style="color: #808080">///</span><span style="color: #008000"> PromoteUserNameBehavior implements IEndpointBehavior and adds a message inspector to the dispatch behavior. Doesn't use any binding parameters, doesn't validate any configuration etc and can't be used in a client (only in a service).
</span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"></summary></span><span style="color: #808080">
</span><span style="color: #000000"> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">class</span><span style="color: #000000"> PromoteUserNameBehavior : IEndpointBehavior
{
</span><span style="color: #0000ff">#region</span><span style="color: #000000"> IEndpointBehavior Members</span><span style="color: #000000">
</span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
</span><span style="color: #0000ff">return</span><span style="color: #000000">;
}
</span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
</span><span style="color: #0000ff">throw</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> Exception(</span><span style="color: #000000">"</span><span style="color: #000000">The method or operation is not implemented.</span><span style="color: #000000">"</span><span style="color: #000000">);
}
</span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(</span><span style="color: #0000ff">new</span><span style="color: #000000"> PromoteUserNameMessageInspector());
}
</span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> Validate(ServiceEndpoint endpoint)
{
</span><span style="color: #0000ff">return</span><span style="color: #000000">;
}
</span><span style="color: #0000ff">#endregion</span><span style="color: #000000">
}
</span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><summary></span><span style="color: #008000">
</span><span style="color: #808080">///</span><span style="color: #008000"> Defines the behavior.
</span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"></summary></span><span style="color: #808080">
</span><span style="color: #000000"> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">class</span><span style="color: #000000"> PromoteUserNameBehaviorElement : BehaviorExtensionElement
{
</span><span style="color: #0000ff">protected</span><span style="color: #000000"> </span><span style="color: #0000ff">override</span><span style="color: #000000"> </span><span style="color: #0000ff">object</span><span style="color: #000000"> CreateBehavior()
{
</span><span style="color: #0000ff">return</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> PromoteUserNameBehavior();
}
</span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">override</span><span style="color: #000000"> Type BehaviorType
{
</span><span style="color: #0000ff">get</span><span style="color: #000000"> { </span><span style="color: #0000ff">return</span><span style="color: #000000"> </span><span style="color: #0000ff">typeof</span><span style="color: #000000">(PromoteUserNameBehavior); }
}
}
}</span></div>
</code></pre></div></div>
<p>Finally we have to sign the assembly using a strong key and add it to the GAC.</p>
<h3 id="configure-the-machineconfig">Configure the machine.config</h3>
<p>As we need BizTalk and the WCF adapter to pick up the need behavior and make it possible to configure our receive port we need to to add the behavior element to the <a href="http://msdn2.microsoft.com/en-us/library/ms229697(VS.71).aspx">machine.config</a>. The easiest way of doing this is to use the new <a href="http://msdn2.microsoft.com/en-us/library/ms732009.aspx">WCF Service Configuration Editor tool</a> and point to the machine.config file.</p>
<p><a href="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4promoteusernamebehavior-gac-2.jpg"><img src="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4promoteusernamebehavior-gac-thumb.jpg" alt="PromoteUserNameBehavior GAC" /></a></p>
<p>After the dll been added and the machine.config file has been saved the the line below should have been added to the [<behaviorExtensions> element](http://msdn2.microsoft.com/en-us/library/aa734726.aspx) (that is if you use the same strong name key as in the sample project I've linked here).</behaviorExtensions></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000ff"><</span><span style="color: #800000">add </span><span style="color: #ff0000">name</span><span style="color: #0000ff">="addCustomWCFProperties"</span><span style="color: #ff0000"> type</span><span style="color: #0000ff">="CustomWCFProperties.Behavior.PromoteUserNameBehaviorElement, AddCustomWCFPropertiesBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=705e34637fdffc54"</span><span style="color: #ff0000"> </span><span style="color: #0000ff">/></span></div>
</code></pre></div></div>
<h3 id="create-the-biztalk-receive-port-and-receive-location">Create the BizTalk Receive Port and Receive Location</h3>
<p>Next thing to do is to start the BizTalk WCF Service Publishing Wizard. Choose to publish a service endpoint and make sure you enable metadata and create a receive location. In this example weāll next choose to āPublish schemas as WCF serviceā and then define our service by naming service operations and so on.</p>
<p>When you then browse to the URL you choose to publish your service to youāll see the nice example of how to instance the service you just defined.</p>
<p><a href="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4wsdl-code-example-2.jpg"><img src="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4wsdl-code-example-thumb.jpg" alt="WSDL code example" /></a></p>
<p>If we then send a request message to service (youāll find a client as part of the <a href="http://www.richardhallgren.com/blogfiles/CustomWCFProperties.zip">attached solution here</a>) and inspect the message and its context properties in BizTalk weāll see that the username of the calling client is nowhere to be found.</p>
<p><a href="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4message-no-username-2.jpg"><img src="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4message-no-username-thumb.jpg" alt="Message No Username" /></a></p>
<h3 id="configure-a-wcf-custom-binding-and-adding-a-endpoint-behavior">Configure a WCF-Custom binding and adding a Endpoint Behavior</h3>
<p>To add the username to the message context weāll need to add our newly created behavior to our service. Weāll do this by switch the service over to use a WCF-Custom binding to enable configuration. We then need to add the URL in the address field, define the binding type to a wsHttpBinding and to add our addCustomeWCFProperties behavior to the list of endpoint behaviors.</p>
<p><a href="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4add-endpoint-behavior-2.jpg"><img src="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4add-endpoint-behavior-thumb.jpg" alt="Add Endpoint behavior" /></a></p>
<blockquote>
>
> [![note](../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4note-thumb.gif)](../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4note-2.gif) NOTE: there is a limitation in the BizTalk WCF implementation in that you can't create the WCF-Custom receive location that uses a HTTP in-process based binding (like the wsHttpBinding used in a WCF-Custom endpoint is) first and then use the WCF Publishing Wizard to only publish a metadata endpoint.
>
>
>
> [Richard Seroter writes about it here](http://www.topxml.com/code/cod-72_10213_biztalk-and-wcf-part-v-publishing-operations-patterns.aspx) and I found the same thing to be true.
>
>
>
> _"This error doesnāt have to do with mixing MEX endpoints and āregularā endpoints in the same IIS web site, but rather, creating MEX endpoints for in-process HTTP bindings seems to trigger this. **Note that an IIS-hosted MEX endpoint CAN be created for IIS-hosted HTTP endpoints, but not for in-process hosted HTTP endpoints."**_
>
>
>
> If you however choose a different binding that Http or (as in this case) publishes the metadata first and then switches over to a custom binding you're ok.
>
>
</blockquote>
<p>If we then post another message to the service and inspect the message weāll see that the behavior actually added a header and that itās part of our BizTalk context properties. The adapter is also smart enough to know that this header isnāt part of the original headers and therefore stores in itās own field within the context properties (youāll find as part of the InboundHeaders block as well).</p>
<p><a href="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4message-username-4.jpg"><img src="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4message-username-thumb-1.jpg" alt="Message Username" /></a></p>
<p>One problem remains - the actual value of the user is nested inside a XML node and the property isnāt promoted.</p>
<h3 id="extract-and-promote-the-value">Extract and promote the value</h3>
<p>To extract and promote the value we use an old fashion pipeline component using the following code in the execute method (the complete project is part of the <a href="http://www.richardhallgren.com/blogfiles/CustomWCFProperties.zip">downloadable sample project</a>).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000"> </span><span style="color: #0000ff">public</span><span style="color: #000000"> IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
{
StringReader reader </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> StringReader(inmsg.Context.Read(</span><span style="color: #000000">"</span><span style="color: #000000">WindowsUserName</span><span style="color: #000000">"</span><span style="color: #000000">, </span><span style="color: #000000">"</span><span style="color: #000000">http://CustomWCFProperties.Schema</span><span style="color: #000000">"</span><span style="color: #000000">).ToString());
</span><span style="color: #0000ff">if</span><span style="color: #000000"> (reader </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">)
{
XPathDocument document </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> XPathDocument(reader);
XPathNavigator navigator </span><span style="color: #000000">=</span><span style="color: #000000"> document.CreateNavigator();
</span><span style="color: #0000ff">string</span><span style="color: #000000"> value </span><span style="color: #000000">=</span><span style="color: #000000"> navigator.SelectSingleNode(</span><span style="color: #000000">"</span><span style="color: #000000">/</span><span style="color: #000000">"</span><span style="color: #000000">).Value;
inmsg.Context.Promote(</span><span style="color: #000000">"</span><span style="color: #000000">WindowsUserName</span><span style="color: #000000">"</span><span style="color: #000000">, </span><span style="color: #000000">"</span><span style="color: #000000">http://CustomWCFProperties.Schema</span><span style="color: #000000">"</span><span style="color: #000000">, value);
}
</span><span style="color: #0000ff">return</span><span style="color: #000000"> inmsg;
}</span></div>
</code></pre></div></div>
<p>All the component does is reading the XML node the value exists inside and then it reads the actual value. Finally it writes the value back and promotes it. To be able to promote the value we also have to have a <a href="http://msdn2.microsoft.com/en-us/library/aa561059.aspx">Property Schema</a> deployed with a corresponding property name and namespace (WindowsUser and <em>http://CustomeWCFProperties.Schema</em> in this case).</p>
<p>The end results looks something like this.</p>
<p><a href="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4message-promoted-username-2.jpg"><img src="../assets/2008/04/windowslivewriterwritingbiztalkcontextpropertiestoamessag-72f4message-promoted-username-thumb.jpg" alt="Message Promoted Username" /></a></p>
<p>The username is extracted and promoted and available for example for tracking or to for example use in a routing scenario.</p>
<p>This technique could of course be used for all kinds of scenarios where you like to add information to the context properties and could potentially replace a lot of the classic scenarios for custom pipelines.</p>
<p>All kind of comments are of course more than welcome!</p>
<p><a href="http://www.richardhallgren.com/blogfiles/CustomWCFProperties.zip">Download the sample solution here</a>.</p>
Random thoughts on SQL Server Adapter and T-SQL Stored Procedures for BizTalk 20062008-02-18T22:36:06+00:00http://richardhallgren.com/random-thoughts-on-sql-server-adapter-and-t-sql-stored-procedures-for-biztalk-2006<p>Writing Stored Procedures is an art of its own. As all of you know itās very different from writing ordinary code and presents its own kind of problems and issues when it comes to performance, builds, version control, testing etc. This post will try and highlight a few points that I find important when it comes to Stored Procedures, and the especially in a BizTalk and integration related scenario.</p>
<p>Consider the simplified procedure below, Iāll use is an example for much of the discussion in the rest of the post. Basically the procedure inserts or updates (based on if the optional EmployeeID exists from before or not) employee information to the Employee table of a database named āTestDBā.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kwrd"></span>
<div><span style="color: #0000ff">Use</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">TestDB</span><span style="color: #ff0000">]</span><span style="color: #000000">
</span><span style="color: #0000ff">Go</span><span style="color: #000000">
</span><span style="color: #0000ff">If</span><span style="color: #000000"> </span><span style="color: #808080">Exists</span><span style="color: #000000">(</span><span style="color: #0000ff">select</span><span style="color: #000000"> </span><span style="color: #808080">*</span><span style="color: #000000"> </span><span style="color: #0000ff">From</span><span style="color: #000000"> dbo.sysobjects </span><span style="color: #0000ff">Where</span><span style="color: #000000"> id </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #ff00ff">object_id</span><span style="color: #000000">(N</span><span style="color: #ff0000">'</span><span style="color: #ff0000">AddEmployee</span><span style="color: #ff0000">'</span><span style="color: #000000">) </span><span style="color: #808080">And</span><span style="color: #000000"> </span><span style="color: #ff00ff">OBJECTPROPERTY</span><span style="color: #000000">(id, N</span><span style="color: #ff0000">'</span><span style="color: #ff0000">IsProcedure</span><span style="color: #ff0000">'</span><span style="color: #000000">) </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #800000; font-weight: bold">1</span><span style="color: #000000">) </span><span style="color: #0000ff">Drop</span><span style="color: #000000"> </span><span style="color: #0000ff">Procedure</span><span style="color: #000000"> AddEmployeeGo
</span><span style="color: #0000ff">Create</span><span style="color: #000000"> </span><span style="color: #0000ff">Procedure</span><span style="color: #000000"> AddEmployee
</span><span style="color: #008000">@EmployeeId</span><span style="color: #000000"> </span><span style="color: #000000; font-weight: bold">Int</span><span style="color: #000000"> </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #808080">-</span><span style="color: #800000; font-weight: bold">1</span><span style="color: #000000">,
</span><span style="color: #008000">@LastName</span><span style="color: #000000"> </span><span style="color: #000000; font-weight: bold">Varchar</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">30</span><span style="color: #000000">),
</span><span style="color: #008000">@FirstName</span><span style="color: #000000"> </span><span style="color: #000000; font-weight: bold">Varchar</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">30</span><span style="color: #000000">),
</span><span style="color: #008000">@MiddleName</span><span style="color: #000000"> </span><span style="color: #000000; font-weight: bold">Varchar</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">30</span><span style="color: #000000">)
</span><span style="color: #0000ff">As</span><span style="color: #000000">
</span><span style="color: #0000ff">Begin</span><span style="color: #000000">
</span><span style="color: #0000ff">Declare</span><span style="color: #000000"> </span><span style="color: #008000">@currentEmployeeId</span><span style="color: #000000"> </span><span style="color: #000000; font-weight: bold">int</span><span style="color: #000000">
</span><span style="color: #0000ff">Declare</span><span style="color: #000000"> </span><span style="color: #008000">@currentAction</span><span style="color: #000000"> </span><span style="color: #000000; font-weight: bold">tinyint</span><span style="color: #000000">
</span><span style="color: #008080">--</span><span style="color: #008080"> Check based on the EmployeeId if the employee exists from before </span><span style="color: #008080">
</span><span style="color: #000000"> </span><span style="color: #0000ff">If</span><span style="color: #000000"> </span><span style="color: #808080">Not</span><span style="color: #000000"> </span><span style="color: #808080">Exists</span><span style="color: #000000">(</span><span style="color: #0000ff">Select</span><span style="color: #000000"> EmployeeId </span><span style="color: #0000ff">From</span><span style="color: #000000"> Employee </span><span style="color: #0000ff">Where</span><span style="color: #000000"> EmployeeId </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #008000">@EmployeeId</span><span style="color: #000000">)
</span><span style="color: #0000ff">Begin</span><span style="color: #000000">
</span><span style="color: #008080">--</span><span style="color: #008080"> Inserts new employee </span><span style="color: #008080">
</span><span style="color: #000000"> </span><span style="color: #0000ff">Insert</span><span style="color: #000000"> </span><span style="color: #0000ff">Into</span><span style="color: #000000"> Employee (LastName,FirstName,MiddleName)
</span><span style="color: #0000ff">Values</span><span style="color: #000000"> (</span><span style="color: #008000">@LastName</span><span style="color: #000000">, </span><span style="color: #008000">@FirstName</span><span style="color: #000000">, </span><span style="color: #008000">@MiddleName</span><span style="color: #000000">)
</span><span style="color: #0000ff">Set</span><span style="color: #000000"> </span><span style="color: #008000">@currentEmployeeId</span><span style="color: #000000"> </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #ff00ff">Scope_Identity</span><span style="color: #000000">()
</span><span style="color: #0000ff">Set</span><span style="color: #000000"> </span><span style="color: #008000">@currentAction</span><span style="color: #000000"> </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #800000; font-weight: bold">1</span><span style="color: #000000">
</span><span style="color: #0000ff">End</span><span style="color: #000000">
</span><span style="color: #0000ff">Else</span><span style="color: #000000">
</span><span style="color: #0000ff">Begin</span><span style="color: #000000">
</span><span style="color: #008080">--</span><span style="color: #008080"> Updates employee </span><span style="color: #008080">
</span><span style="color: #000000"> </span><span style="color: #0000ff">Update</span><span style="color: #000000"> Employee </span><span style="color: #0000ff">Set</span><span style="color: #000000"> LastName </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #008000">@LastName</span><span style="color: #000000">,
FirstName </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #008000">@FirstName</span><span style="color: #000000"> </span><span style="color: #0000ff">WHERE</span><span style="color: #000000"> EmployeeId </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #008000">@EmployeeId</span><span style="color: #000000">
</span><span style="color: #0000ff">Set</span><span style="color: #000000"> </span><span style="color: #008000">@currentEmployeeId</span><span style="color: #000000"> </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #008000">@EmployeeId</span><span style="color: #000000">
</span><span style="color: #0000ff">Set</span><span style="color: #000000"> </span><span style="color: #008000">@currentAction</span><span style="color: #000000"> </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #800000; font-weight: bold">2</span><span style="color: #000000">
</span><span style="color: #0000ff">End</span><span style="color: #000000">
</span><span style="color: #0000ff">Select</span><span style="color: #000000"> </span><span style="color: #008000">@currentEmployeeId</span><span style="color: #000000"> </span><span style="color: #0000ff">As</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">@EmployeeId</span><span style="color: #ff0000">]</span><span style="color: #000000">, </span><span style="color: #008000">@currentAction</span><span style="color: #000000">
</span><span style="color: #0000ff">As</span><span style="color: #000000"> </span><span style="color: #ff0000">[</span><span style="color: #ff0000">@ProcedureAction</span><span style="color: #ff0000">]</span><span style="color: #000000"> </span><span style="color: #0000ff">For</span><span style="color: #000000"> Xml Path (</span><span style="color: #ff0000">'</span><span style="color: #ff0000">Response</span><span style="color: #ff0000">'</span><span style="color: #000000">)
</span><span style="color: #0000ff">End</span><span style="color: #000000">
</span><span style="color: #0000ff">Go</span></div>
</code></pre></div></div>
<h3 id="builds-and-version-control">Builds and version control</h3>
<p>I always try to have the complete database version controlled. One solution to this that some people advocate is to have a central development database. I have however always found it to be a lot of hassle with overwriting each others changes and so on and always try to make it possible for each developer to build a local version of the database for development. It should also be possible to always check out the latest version and run it to build all the database objects - no matter what you have from before. This is of course a bit tricky when it comes to the actual tables as you might have data and so on (in my opinion it shouldnāt be the case during development but thatās another post discussing test data for the database etc).</p>
<p>When it however comes to Stored Procedure as in this post itās easy - <strong>drop the old one if it exists and create the new one as in the example</strong>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000ff">If</span><span style="color: #000000"> </span><span style="color: #808080">Exists</span><span style="color: #000000">(</span><span style="color: #0000ff">select</span><span style="color: #000000"> </span><span style="color: #808080">*</span><span style="color: #000000"> </span><span style="color: #0000ff">From</span><span style="color: #000000"> dbo.sysobjectsWhere id </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #ff00ff">object_id</span><span style="color: #000000">(N</span><span style="color: #ff0000">'</span><span style="color: #ff0000">AddEmployee</span><span style="color: #ff0000">'</span><span style="color: #000000">) </span><span style="color: #808080">And</span><span style="color: #000000"> </span><span style="color: #ff00ff">OBJECTPROPERTY</span><span style="color: #000000">(id, N</span><span style="color: #ff0000">'</span><span style="color: #ff0000">IsProcedure</span><span style="color: #ff0000">'</span><span style="color: #000000">) </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #800000; font-weight: bold">1</span><span style="color: #000000">) </span><span style="color: #0000ff">Drop</span><span style="color: #000000"> </span><span style="color: #0000ff">Procedure</span><span style="color: #000000"> AddEmployee
</span><span style="color: #0000ff">Go</span><span style="color: #000000">
</span><span style="color: #0000ff">Create</span><span style="color: #000000"> </span><span style="color: #0000ff">Procedure</span><span style="color: #000000"> AddEmployee </span><span style="color: #008000">@EmployeeId</span><span style="color: #000000"> </span><span style="color: #000000; font-weight: bold">Int</span><span style="color: #000000"> </span><span style="color: #808080">=</span><span style="color: #000000"> </span><span style="color: #808080">-</span><span style="color: #800000; font-weight: bold">1</span><span style="color: #000000">, ...</span></div>
</code></pre></div></div>
<p>If found <a href="http://www.codinghorror.com/blog/archives/001050.html">this article</a> by Jeff Atwood over at <a href="http://www.codinghorror.com/blog/">Coding Horror</a> (and <a href="http://odetocode.com/Blogs/scott/archive/2008/01/30/11702.aspx">the articles</a> by K. Scott Allen it links to) very good on how to think about version control database objects.</p>
<h3 id="idempotent-procedures">Idempotent procedures</h3>
<p>In complex integration solution itās a common problem with multiple messages - sending systems might send the same message twice for a number of reasons and one will end up with a shaky system if that causes an error in the integration. Iāve also seen solutions to this problem where a check is done against the database (say from a BizTalk orchestration) and based on that result a decision is made to call an update or an insert procedure. In my opinion that just unnecessary complexity and database communication. I believe <strong>one should try and handle whether to update or insert inside the procedure as long as thatās possible and effective</strong>.</p>
<p>I in the AddEmployee Stored Procedure example might receive a EmployeeID as an input parameter and based on a check inside the procedure if the employee exists from before with that id a post is either updated or inserted.</p>
<h3 id="response-message">Response message</h3>
<p>I generally always want two things in return from a Store Procedure like the one in the AddEmployee example (In a select based procedure that would of course be very different as we like all the data in return).</p>
<ol>
<li>
<p>The id that been added or changed</p>
</li>
<li>
<p>What action thatās been performed (insert or update)</p>
</li>
</ol>
<p>What action that was performed is a good idea to return as itās quite usual to use this in for example BAM tracking or other logging and so on (we might want know how many employees that was added versus updated for example).</p>
<p>Using the <a href="http://msdn2.microsoft.com/en-us/library/ms189885.aspx">Xml Path syntax</a> for generating the Xml response (thanks again Nick for a <a href="http://www.modhul.com/2008/01/23/an-easier-way-to-do-complex-for-xml-explicit/">great post</a>) from the procedure has made it even simpler to actually skip using the <a href="Add Generated Item">Add Generated Item</a> option in BizTalk. All you have think about is to <strong>set name of the child node the request root node to the same name as the procedure</strong> (in this case AddEmployee). Also remember that the type should be <strong>set up as a Multi-Part Message Type in the orchestrations</strong> you use it from and that the **Receive Pipeline you choose in the Send Port must use a Xml Disassembler component **(XmlReceive pipeline will do fine unless you have your custom pipeline for some reason).</p>
<p><a href="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235schemadbtest-2.jpg"><img src="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235schemadbtest-thumb.jpg" alt="SchemaDBTest" /></a></p>
<h3 id="error-handling">Error handling</h3>
<p>Some people might find it strange that I donāt have any error handling in my Stored Procedures but in most cases an error in the procedure will cause an exception in the port communication with the database and thatās fine. If Iād like to handle that error Iāll handle that either in the orchestration or using other mechanisms in BizTalk like <a href="http://msdn2.microsoft.com/en-us/library/aa578516.aspx">Failed Message Routing</a> etc. <strong>If I canāt handle the error in the procedure I donāt see a reason to catch it.</strong></p>
<h3 id="security">Security</h3>
<p>Iāve seen to many cases where developers actually used the user and password login option available on the database adapter and port. Even if the credentials are safe in the SSO database there is a risk youāll end up in a mess with login data spread all over the BizTalk administration. <strong>One should always use try to use Windows NT Integrated Security!</strong></p>
<p>Even more common than the above is to have a user that part of the administrators group or similar to hit the database - <strong>donāt!</strong> I usually try an set up one Host to run as in all the communication with a specific database (Could also be a Host for that database and that BizTalk Application so that different applications have their own Host). Iāll then give that specific user the **least privileges **needed in the specific database.</p>
<p>In the AddEmployee and TestDB example Iād create <strong>a new Group in the AD called for example āBizTalk TestDB Usersā</strong>. Iād then create <strong>a User in the AD called āBizTalk TestDB Userā</strong>. Itās based on this Iād then create a Host in BizTalk referencing the above created Group.</p>
<p><a href="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235testdbhost-2.jpg"><img src="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235testdbhost-thumb.jpg" alt="TestDBHost" /></a></p>
<p>Finally weāll create a Host Instance and make a Send Handler of it on the SQL Server Adapter.</p>
<p><a href="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235dbtesthostinstance-4.jpg"><img src="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235dbtesthostinstance-thumb-1.jpg" alt="DBTestHostInstance" /></a></p>
<p><a href="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235dbtestsqladapter-2.jpg"><img src="../assets/2008/02/windowslivewritertsqlstoreproceduresforbiztalk-c235dbtestsqladapter-thumb.jpg" alt="DBTestSqlAdapter" /></a></p>
<p>Now we can <strong>set the least required privileges on the āBizTalk TestDB Usersā in Sql Server as that the Group the User belongs thatāll hit the database</strong>. In this case this means granting the Group to the <a href="http://msdn2.microsoft.com/en-us/library/aa547356.aspx">standard BizTalk required privileges for a Host</a> besides granting it Execute right on the AddEmployee Stored Procedure.</p>
<p>Something I missed? How do you handle your database communication and security in your BizTalk implementations?</p>
A loosely coupled Scatter-and-Gather implementation In BizTalk 20062008-01-15T17:40:05+00:00http://richardhallgren.com/a-loosely-coupled-scatter-and-gather-implementation-in-biztalk-2006<h3 id="why-loose-coupling">Why loose coupling?</h3>
<p>There was a <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2660792&SiteID=1">question in Microsoft BizTalk forums</a> the other day about how one could implement a <a href="http://msdn2.microsoft.com/en-us/library/aa561967.aspx">Scatter and Gather pattern</a> in a more <a href="http://en.wikipedia.org/wiki/Loose_coupling">loosely coupled</a> fashion.</p>
<p>Most examples on the implementation of this pattern in BizTalk use the Call Shape functionality available in BizTalk orchestrations. This however creates a hard coupling between the āScatter orchestrationā and itās āpartner orchestrationsā. The downside of that is that when one adds or removes a partner the whole solution has to be recompiled and redeployed.</p>
<p>If one however could use the publish-subscribe architecture in the MessageBox to route messages between the āGather orchestrationā and itās partners, itād be possible to add partners without having to worry about the rest of the solution. This post shows and example on how to implement a solution like that.</p>
<p>#</p>
<h3 id="the-biztalk-process-in-steps">The BizTalk process in steps</h3>
<blockquote>
>
> [![Aa559774_note(ja-jp,MSDN_10)](../assets/2008/01/aa559774-noteja-jpmsdn-10-thumb.gif)](../assets/2008/01/aa559774-noteja-jpmsdn-10.gif) NOTE: Notice the difference between the **Partners**Request, the **Partners**Response, the **Partner**Request and the **Partner**Response messages. The names are unfortunately very similar.
>
>
>
> The **Partners**Request and **Partners**Response messages are used for communication between the Scatter and the Gather orchestrations. It's also a **Partners**Request message that activates the process.
>
>
>
> **Partner**Response and **Partner**Request are used for communicating between the Scatter and the Gather orchestration and all the partner orchestrations.
>
> </blockquote>
<ol>
<li>
<p><strong>Request and scatter</strong> <br />
A PartnersRequest message is received. This message is an empty message and is only used for activating the process in this example scenario. The PartnersRequest message is consumed by the Scatter orchestration. The Scatter orchestration creates one PartnerRequest message. The orchestration also generates a unique key called a RequestID and start a correlation combining that that id and the PartnersRequest MessageType. Finally it post the PartnerRequest message to message box, writes the generated RequestID to the request messages context (RequestID is a MessageContextPropertyBase based context property) and dehydrates itself. <br />
<a href="../assets/2008/01/looselycoupledscattergather1.jpg"><img src="../assets/2008/01/looselycoupledscattergather1-thumb.jpg" alt="LooselyCoupledScatterGather1" /></a></p>
</li>
<li>
<p><strong>Partners</strong> <br />
All the enlisted Partner orchestrations pick up the PartnerRequest message from the message box. These orchestration then communicates with their specific data source (could be a service, database, file or whatever), receives a response. Finally these orchestrations transform the response they received and creates a PartnerResponse message thatās posted to the message box. Notice that the RequestID that was generated by the Scatter orchestration is also part of the context of the newly created PartnerResponse message.</p>
</li>
<li>
<p><strong>Gather</strong> <br />
The PartnerResponse messages are routed to the Gather orchestration. This orchestration uses a Singleton pattern based on the RequestID which all PartnerResponse messages carried with them in their context. This means that itāll receive all the PartnerResponse messages containing that same RequestID into the same orchestration instance (ergo all the Partners that were activated by the request message being sent from one Scatterer). For each message instance it receives it add itās price to a total price variable. When the Gather orchestration has received all the PartnerResponse messages (the orchestration knows how many Partners responses it should expect from one Scatterer orchestration and we can timeout if we donāt get all expected with a timeframe) the total price we calculated is written to a PartnersResponse message.</p>
</li>
<li>
<p><strong>Response</strong> <br />
This message is routed back the Scatter orchestration by using the correlation it initialized in the start. Itās finally this orchestration that send the final outgoing message (a PartnersResponse message).</p>
</li>
</ol>
<h3 id="example-solution">Example solution</h3>
<p>An example of the implementation can be <a href="http://www.richardhallgren.com/blogfiles/LooselyCoupledScatterGatherExample.zip">downloaded from here</a>.</p>
<p>The solution contains five different schemas.</p>
<ol>
<li>
<p><strong>PartnersResponse</strong> <br />
Used for initializing the process.</p>
</li>
<li>
<p><strong>PartnersRequest</strong> <br />
Send from the Gather orchestration to the Scatter orchestration. Itās also the final result and outgoing message from the process.</p>
</li>
<li>
<p><strong>PartnerRequest</strong> <br />
Picked up and activates all enlisted Partner orchestrations.</p>
</li>
<li>
<p><strong>PartnerRequest</strong> <br />
Send from the Partner orchestration containing the result from the Partner Service and send to the Gather orchestration.</p>
</li>
<li>
<p>**LooselyCoupledScatterGatherExampleProperties <br />
**Property schema for storing the RequestID and to correlate all the PartnerResponses as well as the final PartnersResponse back to the Scatter orchestration.</p>
</li>
</ol>
<h4 id="five-orchestrations">Five orchestrations</h4>
<ol>
<li>
<p>**Scatterer orchestration <br />
**The āmain orchestrationā that receives a request message from outside and āscattersā party requests to all the party orchestrations.</p>
</li>
<li>
<p>**Gatherer orchestration <br />
**Gatherer orchestration that gathers all the responses from the partners and transforms these to a reply that is being routed back to the Scatterer and back out.</p>
</li>
<li>
<p><strong>Partner1</strong>, <strong>Partner2</strong> and **Partner3 orchestration <br />
**Partner orchestrations that communicates to different services and receives price information.</p>
</li>
</ol>
<h4 id="setting-up-and-testing-the-example-solution---its-easy">Setting up and testing the example solution - itās easy!</h4>
<p>When the solution is built and deployed one needs to setup and bind two ports; one outgoing port and one incoming port (this could also be a Request-Response port by changing the port type in the Scatterer orchestration). <strong>Thatās it!</strong></p>
<p>Enlist and start everything by dropping a PartnersRequest test message (youāll find one among the zipped files) in the incoming folder. A PartnersResposne message should then be published in the outgoing folder containing a calculated price from all the Partner orchestrations.</p>
<p>Test message and a binding file are part of the <a href="http://www.richardhallgren.com/blogfiles/LooselyCoupledScatterGatherExample.zip">zipped solution</a>.</p>
<h3 id="what-would-be-different-in-real-life-solution">What would be different in āreal lifeā solution?</h3>
<p>Iāve made some major simplifications in this example to make it easy for setting it up and test the concept. These would very different in a ārealā solution.</p>
<h4 id="partner-services">Partner Services</h4>
<h4 id="the-partner-orchestrations-are-very-simple-they-actually-dont-communicate-with-outside-world-at-all-all-the-do-is-setting-a-hard-coded-price-and-post-a-response-in-a-real-solution-these-would-not-be-part-of-the-same-solution-as-the-scatter-and-gather-orchestration-otherwise-we-would-be-force-to-redeploy-when-adding-a-partner-orchestration-to-the-dll">The Partner orchestrations are very simple. They actually donāt communicate with outside world at all. All the do is setting a hard coded price and post a response. In a real solution these would <strong>not</strong> be part of the same solution as the Scatter and Gather orchestration (otherwise we would be force to redeploy when adding a Partner orchestration to the dll).</h4>
<p>The Partner orchestrations would also communicate with some sort of outbound source like a web service or database for example. This would however complicate the setup therefore Iāve skipped that part in the example.</p>
<h4 id="managing-partners">Managing partners</h4>
<p>One of the benefits with a loosely coupled implementation is the possibility to add and remove Partner orchestrations without having redeploy the rest of the solution. Using this implementation the Gatherer orchestration needs to know how many Partner responses it should wait for before timing out. This requires that value being set in a config file or something similar. In this example the number of Partners are hard coded into the Gather orchestration (itās set to 3 Partners) to simplify the setup.</p>
<h3 id="final-thoughts">Final thoughts</h3>
<p>Knowing how to create loosely coupled solutions like this is good knowledge to have. Itās my own <a href="http://msdn.microsoft.com/msdnmag/issues/07/05/BizTalk/#S2">and others</a> belief that this architecture makes it possible to create more robust and separated solutions that one can update without having to do a lot a work and disturb the current processes. Itās however not the best solution performancewise as it adds a lot of extra hits on the MessageBox database and generates more work for the MessageAgent.</p>
<p>There are also a few things to watch out for:</p>
<h4 id="eternal-loops">Eternal loops</h4>
<p>It easy to end up in a situation where youāre subscribing to the same message as you posting to the MessageBox. Thatāll create and endless loop and cause a lot disturbance before youāll find it. Think through and document you subscriptions!</p>
<h4 id="correlations-for-promoting-values">Correlations for promoting values</h4>
<p>When doing a direct post in BizTalk most properties are not promoted. To <a href="http://geekswithblogs.net/bloesgen/archive/2006/04/24/76278.aspx">force you properties to be promoted</a> youāll have to initialize a correlation on the property as you send it. I canāt say I like this. There should be a other way of saying that one wants it promoted.</p>
<p>A couple of other useful articles as we on the subject:</p>
<ul>
<li>
<p><a href="http://blogs.msdn.com/biztalk_core_engine/archive/2004/07/22/191888.aspx">Is there a pub/sub system underneath BizTalk?</a></p>
</li>
<li>
<p><a href="http://blogs.msdn.com/biztalk_core_engine/archive/2004/08/03/206589.aspx">Okay, so where do subscriptions come from?</a></p>
</li>
<li>
<p><a href="http://weblogs.asp.net/gsusx/archive/2005/01/08/349177.aspx">Starting BizTalk Server 2004 orchestrations using the MessageAgent.</a></p>
</li>
</ul>
<p><a href="http://www.richardhallgren.com/blogfiles/LooselyCoupledScatterGatherExample.zip">Download the example orchestration</a> and let me know how you used it and what your solution looks like!</p>
Speaking at Developer Summit 2008!2007-12-20T13:26:59+00:00http://richardhallgren.com/speaking-at-developer-summit-2008<p><a href="http://www.expertzone.se/dev08/"><img src="../assets/2007/12/devsum.jpg" alt="Developer Summit 2008" /></a>Whoho! Iāll be speaking at <a href="http://www.expertzone.se/dev08/">Developer Summit 2008</a>. Developer Summit is a conference hosted by <a href="http://www.cornerstone.se/">Cornerstone</a>, itās being held in Stockholm between the 9th and 11th of April 2008.</p>
<p>Iāll be doing a talk on <a href="http://en.wikipedia.org/wiki/Reference_Data_Management">Master Data Management</a> (MDM) for the Enterprise using BizTalk 2006. Basically Iāll present some basic theory behind the MDM concept and how it relates to <a href="http://en.wikipedia.org/wiki/Service-oriented_architecture">SOA</a>. Then Iāll relate all that to a customer case I recently worked on solving a MDM requirement. Finally Iāll be showing a short demo where I publish some Master Data and update all subscribers to it. In the same demo Iāll also demonstrate on how to monitor the process using <a href="http://www.microsoft.com/technet/prodtechnol/biztalk/2006/evaluate/overview/default.mspx#EWC">Business Activity Monitoring</a>.</p>
<p>Sound interesting? Something specific you think should be in the presentation? Let me know!</p>
<p>Hope to see you there!</p>
Removing namespace from outgoing messages2007-12-20T12:38:24+00:00http://richardhallgren.com/removing-namespace-from-outgoing-messages<p>Way to often I get a request to deliver a message from BizTalk without any <a href="http://en.wikipedia.org/wiki/XML_namespace">XML namespace</a>. Comments like the one below arenāt that rare.</p>
<blockquote>
>
> Why do you put those "ns0" I front of every tag!? We can't read the XML when it's written like that! All our XPath and XSLT seems to fail.
>
>
>
> We don't want _**<ns0:OutMessage xmlns:ns0="Acme.Messages.OutMessage/1.0">**_ ... We expect the messages from you to be like _**<OutMessage>**_ ...
>
>
>
> Is that some BizTalk specific?
>
> </blockquote>
I always try to explain what XML namespaces are, and why it's a good idea to use them (especially when it comes to versioning of messages). Sometimes it's just impossible to get people to understand the advantages of using it and to persuade them to change their solutions to handle XML namespaces. It's in these cases it'll be up to the implementation in BizTalk to remove the namespace.
### How to remove XML namespace
There are a couple of ways of achieving this, we can use [.NET code](http://www.pluralsight.com/blogs/keith/archive/2005/10/19/15714.aspx) that we call in a pipeline or in an orchestration. But we can also handle this using XSL - and that's what I'll show in this post. The XSL stylesheet below will remove all XML namespaces while transforming the message. Basically it just copies the nodes, attributes and it's values using the [local-name()](http://www.webhostingsearch.com/blogs/richard/nevermind-the-xml-namespaces-in-xpath-expressions/) function to ignore the XML namespaces.
<div><span style="color: #0000ff"><?</span><span style="color: #ff00ff">xml version="1.0" encoding="utf-8"</span><span style="color: #0000ff">?></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:stylesheet </span><span style="color: #ff0000">version</span><span style="color: #0000ff">="1.0"</span><span style="color: #ff0000">
xmlns:xsl</span><span style="color: #0000ff">="http://www.w3.org/1999/XSL/Transform"</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:template </span><span style="color: #ff0000">match</span><span style="color: #0000ff">="/"</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:copy</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:apply-templates </span><span style="color: #0000ff">/></span><span style="color: #000000">
</span><span style="color: #0000ff"></</span><span style="color: #800000">xsl:copy</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"></</span><span style="color: #800000">xsl:template</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:template </span><span style="color: #ff0000">match</span><span style="color: #0000ff">="*"</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:element </span><span style="color: #ff0000">name</span><span style="color: #0000ff">="{local-name()}"</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:apply-templates </span><span style="color: #ff0000">select</span><span style="color: #0000ff">="@* | node()"</span><span style="color: #ff0000"> </span><span style="color: #0000ff">/></span><span style="color: #000000">
</span><span style="color: #0000ff"></</span><span style="color: #800000">xsl:element</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"></</span><span style="color: #800000">xsl:template</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:template </span><span style="color: #ff0000">match</span><span style="color: #0000ff">="@*"</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:attribute </span><span style="color: #ff0000">name</span><span style="color: #0000ff">="{local-name()}"</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:value-of </span><span style="color: #ff0000">select</span><span style="color: #0000ff">="."</span><span style="color: #ff0000"></span><span style="color: #0000ff">/></span><span style="color: #000000"></span>
<span style="color: #0000ff"></</span><span style="color: #800000">xsl:attribute</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"></</span><span style="color: #800000">xsl:template</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:template </span><span style="color: #ff0000">match</span><span style="color: #0000ff">="text() | processing-instruction() | comment()"</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"><</span><span style="color: #800000">xsl:copy </span><span style="color: #0000ff">/></span><span style="color: #000000">
</span><span style="color: #0000ff"></</span><span style="color: #800000">xsl:template</span><span style="color: #0000ff">></span><span style="color: #000000">
</span><span style="color: #0000ff"></</span><span style="color: #800000">xsl:stylesheet</span><span style="color: #0000ff">></span></div>
### Apply the XSL transformation
We can use this XSL stylesheet in a ordinary BizTalk map on the send port using the _Custom XSL Path_ property in the BizTalk Mapper. The result is that the XSL we usually generate in the mapping tool will be overridden by our own XSL stylesheet. The figure below shows how we use the property windows of the grid in the BizTalk Mapper to set the property and point the Mapper to our XSLT document.
[![](../assets/2007/12/windowslivewriterremovingnamespacefromoutgoingmessage-a4edxsltpath-thumb11.jpg)](../assets/2007/12/windowslivewriterremovingnamespacefromoutgoingmessage-a4edxsltpath51.jpg)
**But what if we already have a map on the send port and it's that already transformed message we like to remove the namespace from?** One possibility is to use the [_XSLT Transform_ pipeline component](http://msdn2.microsoft.com/en-us/library/aa561389.aspx) that comes with the BizTalk 2006 SDK. It's usually located at _C:\Program Files\Microsoft BizTalk Server 2006\SDK\Samples\Pipelines\XslTransformComponent\XslTransform_ on your development machine. I've written about this sample component before [here](http://www.webhostingsearch.com/blogs/richard/transform-and-split-messages-using-an-xslt-transformation-pipeline-component-and-the-xmldissasembler/) were I used it another scenario.
The figure below shows how we use the property windows of the _XSLT Transform Component_ in a pipeline in the Pipeline designer tool to set the path to our XSLT stylesheet.
[![](../assets/2007/12/windowslivewriterremovingnamespacefromoutgoingmessage-a4edxsltpath2-thumb1.jpg)](../assets/2007/12/windowslivewriterremovingnamespacefromoutgoingmessage-a4edxsltpath221.jpg)
### Final thoughts
The XSLT Transform component is far from perfect and the obvious problem is of course that the component loads the whole message into memory using the [XmlDocument class](http://msdn2.microsoft.com/en-us/library/system.xml.xmldocument.aspx) to read the message. That means that this solution isn't for those scenarios where you'll have huge messages coming in by the thousands. But for those cases where you have normal sized messages and you have a idea of the traffic you receive, it's a quick and easy solution.
Any comments on the pro and cons on this solution and how you usually solve this scenario will be appreciated!
<blockquote>
>
> **UPDATE #1: **Make sure you don't miss [Johan Hedbergs solution](http://blogical.se/blogs/johan/archive/2008/01/07/removing-xml-namespace-in-a-pipeline-component.aspx) to this problem. Basically he solved it using the [Microsoft.BizTalk.Streaming.dll](http://technet.microsoft.com/en-us/library/microsoft.biztalk.streaming.aspx) which will give you better memory management.
>
>
</blockquote>
<blockquote>
>
> **UPDATE #2: **Based on the comments to this post I've posted an "updated" post [here](http://www.richardhallgren.com/removing-xml-namespaces-revisit/) solving this using ordinary mapping and defining a schema without a XML namespace - easier and more correct.
>
> </blockquote>
</OutMessage></ns0:OutMessage></blockquote>
Dealing with cXML based messages in BizTalk2007-11-29T16:33:30+00:00http://richardhallgren.com/dealing-with-cxml-based-messages-in-biztalk<p><a href="http://cxml.org/">cXML</a> (commerce eXtensible Markup Language) is a XML based standard for communication of data related to electronic commerce. The problem from a BizTalk perspective is that they <strong>donāt publish any <a href="http://en.wikipedia.org/wiki/XML_Schema">XML schemas</a></strong> (XSD), only <a href="http://en.wikipedia.org/wiki/Document_Type_Definition">Document Type Definition</a> (DTD).</p>
<p>When trying to generate a schema based on a DTD using the functionality in BizTalk (via <a href="http://msdn2.microsoft.com/en-us/library/ms944737.aspx">Add Generated Items</a>) one ends up with a schema split of three files that really doesnāt make any sense (<a href="http://www.altova.com/products/xmlspy/xml_editor.html">XmlSpy</a> doesnāt do a very good job either ā¦). So after a while I found <a href="http://www.modhul.com/schema-repository-cxml/">Nick Heppleston schema repository</a>! After some tweaking I actually had a cXML Order schema in the version I was looking for! Thanks Nick!</p>
<p>The next set of problems was to handle <strong>the lack</strong> of <a href="http://en.wikipedia.org/wiki/XML_namespace">XML namespace</a> and the <a href="http://msdn2.microsoft.com/en-us/library/ms256059.aspx">DOCTYPE declaration</a> that messages validating against DTD carries on top.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><?</span><span style="color: #FF00FF; ">xml version="1.0" standalone="no"</span><span style="color: #0000FF; ">?></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><!</span><span style="color: #FF00FF; ">DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.014/cXML.dtd"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">cXML </span><span style="color: #FF0000; ">xml:lang</span><span style="color: #0000FF; ">="en-US"</span><span style="color: #FF0000; "> payloadID</span><span style="color: #0000FF; ">="2007117.25919@Contempus"</span><span style="color: #FF0000; "> timestamp</span><span style="color: #0000FF; ">="2007-11-07T11:06:16+01:00"</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>To handel these two issues I set up a receive pipeline that looked like the one below.</p>
<p><a href="../assets/2007/11/windowslivewriterba0c14911562-ef39pipeline32.jpg"><img src="../assets/2007/11/windowslivewriterba0c14911562-ef39pipeline-thumb12.jpg" alt="" /></a></p>
<h1 id="remove-the-doctype-declaration">Remove the DOCTYPE declaration</h1>
<p>First I created a pipeline component to remove the DOCTYPE node. Itās simple code using <a href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a> to find the DOCTYPE node, replace it with an empty string and return the message.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; ">public</span><span style="color: #000000; "> IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
{
</span><span style="color: #0000FF; ">string</span><span style="color: #000000; "> messageString </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> StreamReader(inmsg.BodyPart.Data).ReadToEnd();
Regex doctypePattern </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> Regex(</span><span style="color: #000000; ">"</span><span style="color: #000000; "><!DOCTYPE.+?></span><span style="color: #000000; ">"</span><span style="color: #000000; ">);
messageString </span><span style="color: #000000; ">=</span><span style="color: #000000; "> doctypePattern.Replace(messageString, </span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">.Empty);
MemoryStream memStream </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> MemoryStream();
</span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">[] data </span><span style="color: #000000; ">=</span><span style="color: #000000; "> Encoding.UTF8.GetBytes(messageString);
memStream.Write(data, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">, data.Length);
memStream.Seek(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">, SeekOrigin.Begin);
inmsg.BodyPart.Data </span><span style="color: #000000; ">=</span><span style="color: #000000; "> memStream;
</span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> inmsg;
}</span></div>
</code></pre></div></div>
<h1 id="set-an-xml-namespace">Set an XML namespace</h1>
<p>Secondly I used <a href="http://seroter.wordpress.com/2007/02/11/add-namespace-to-inbound-biztalk-messages/">Richard Seroterās post</a> on how to change the SetNSForMsg component to add a XML namespace. Thatās the second component showing in the decode stage of the pipeline.</p>
<p>Arrow number 3 shows how the SetMsgNS exposes a property that allows us to set the namespace that we can configure per pipeline. In this case Iāve set it to _http://schemas.modhul.com/cXML/1.2.014/OrderRequest__ _which is the namespace of the cXML schema Iām currently working agains.</p>
<p>In the end weāll have a message with the following declaration and root node.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><?</span><span style="color: #FF00FF; ">xml version="1.0" encoding="utf-16" standalone="no"</span><span style="color: #0000FF; ">?></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">cXML </span><span style="color: #FF0000; ">xml:lang</span><span style="color: #0000FF; ">="en-US"</span><span style="color: #FF0000; "> payloadID</span><span style="color: #0000FF; ">="2007117.25919@Contempus"</span><span style="color: #FF0000; "> xmlns</span><span style="color: #0000FF; ">="http://schemas.modhul.com/cXML/1.2.014/OrderRequest"</span><span style="color: #FF0000; "> timestamp</span><span style="color: #0000FF; ">="2007-11-07T11:06:16+01:00"</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>Now weāre ready to start mapping!</p>
A pattern for Ordered Delivery using orchestrations2007-11-01T13:37:46+00:00http://richardhallgren.com/a-pattern-for-ordered-delivery-using-orchestrations<p><a href="http://msdn2.microsoft.com/en-us/library/aa559637.aspx">Ordered Delivery</a> is a great feature of BizTalk 2006. The problem is however that as soon as one introduce a orchestration in the process it doesnāt work. The Ordered Delivery option on ports in BizTalk 2006 ensures two things today:</p>
<ol>
<li>Messages are published to the MessageBox in the same order as they were consumed by the Receive Port.</li>
<li>Messages are consumed from the MessageB0ox and published to the end destination by the send port in the same order as they were persisted in the MessageBox.</li>
</ol>
<h1 id="whats-the-problem">Whatās the problem?</h1>
<p>Fine. But if we introduce an orchestration each message being persisted in the the MessageBox will start itās own orchestration instance. These instances could (and in many cases will) finish in different order than they started. This means that we loose the correct order of the messages one they are persisted back to the MessageBox from the orchestration instance.</p>
<p>The above ālimitationā is well known and the solution to this has always been a <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bts_2004wp/html/956fd4cb-aacc-43ee-99b6-f6137a5a2914.asp">Sequential Orchestration</a> pattern (also called Singleton Orchestration). Basically this correlates messages from for example a specific Receive Port of a particular Message Type. This ensures that only one instance of the orchestration will be started and we can keep the order of the messages. Weāve experienced a lot of problems using this this kind of solution for Ordered Delivery - all from <a href="http://msdn2.microsoft.com/en-us/library/bb203853.aspx">Zombies</a> to them using huge amounts of memory and so on.</p>
<h1 id="microsofts-new-solution">Microsoftās new solution</h1>
<p>Now <a href="http://msdn2.microsoft.com/en-us/library/Bb851740.1542441d-d33a-4634-898f-c89efb0d94fa(en-us,MSDN.10).gif"><img src="../assets/2007/11/windowslivewriterapatternforordereddeliverythatworksfinal-c24buntitled31.gif" alt="" /></a>it finally looks like this problem is about to be solved! Microsoft released a <a href="http://msdn2.microsoft.com/en-us/library/bb851740.aspx">white paper</a> recently (download it <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=02c5fd53-fee9-44fc-a780-5d1d34ee8754&displaylang=en">here</a> - found it via <a href="http://seroter.wordpress.com/">Richard Seroterās blog</a>) to solve these problems in a other way. It basically means that a pipeline will stamp the messages with a sequence number as they enter BizTalk (the messages are then in order as weāre then using Ordered Delivery on the port). Then one can have as many orchestration as one like processing these messages and publish them back to the MessageBox (now possibly out of order but with a sequence number stamped on them). The last business orchestration will set a ādestinationā property that will route the message to a resequence orchestration. This orchestration resequences the messages and decides by checking the last sequence number it sent out if the current message should be sent out or put back on queue.</p>
<h1 id="conclusion">Conclusion</h1>
<p>My biggest concern in this solution is that is still based on a singleton. Weāve had cases where where the send procedure been extremely slow (for example when we used SOAP and had a slow Web Service in the other end), then the orchestration has built up in memory as it queued messages internally. However it looks like this solution is well thought through with a āflush queueā functionality, stop message, some ideas on how to handle errors (remember that if the singleton fails and you donāt handle this your processes stop) and so on.</p>
<p><a href="http://msdn2.microsoft.com/en-us/library/bb851740.aspx">Read it</a> and please let me know what you think!</p>
Why BizTalk isnāt an ESB today and is it heading there?2007-09-25T14:01:57+00:00http://richardhallgren.com/why-biztalk-isnt-an-esb-today-and-is-it-heading-there<p>Iāve written about the ESB concept <a href="http://www.webhostingsearch.com/blogs/richard/index.php">before</a> and what I think an ESB architecture is. In the posts comments there were some discussion about if BizTalk is an ESB or not. And if not - <strong>why not</strong>?</p>
<p>I think <a href="http://dotnet.sys-con.com/read/121831.htm">this article</a> does a great job in explaining and discussing this subject. Basically it says that the main reason for BizTalk not qualifying as an ESB today (I know about the <a href="http://www.codeplex.com/esb">ESB Guidance</a> - we get there ;)) is because of itās āall-or-nothingā packaging. What that means is that itās different functionality can not be separately deployed a cross a bus structure. For example; the scenario of having the transformation functionality in one place and the routing functionality in another just isnāt possible in todayās architecture. Today you install the full product in one place.</p>
<p>I think Iāve personally have learnt to live with this limitation. On the other hand I can see that the possibility of splitting parts up definitely changes things as the possibility of reuse and single point of failure problems etc.</p>
<h1 id="is-biztalk-going-the-esb-way">Is BizTalk going the ESB way?</h1>
<p>I still havenāt had as much time as Iād like to examine the <a href="http://www.codeplex.com/esb">ESB Guidance</a> but I look forward to see how they worked around the problem described above.</p>
<p><a href="../assets/2007/09/windowslivewriterisbiztalkanesb-e886microsoftesbtechnicaloverview51.jpg"><img src="../assets/2007/09/windowslivewriterisbiztalkanesb-e886microsoftesbtechnicaloverview-thumb31.jpg" alt="" /></a> Just looking at this architecture image shows that theyāve split things up in a new way and that each part is accessible trough services - nice! Could this be the future architecture of BizTalk server? What do you think?</p>
<p>Iāll try and install the ESB project as soon as I get some more time on my hands. In the mean time Iād love some tips and comments on articles and other reading on the experiences of the ESB Guidance project.</p>
SOA isnāt response request2007-08-10T17:48:17+00:00http://richardhallgren.com/soa-isnt-response-request<p>Iāve often been told that one of the biggest mistakes people make when implementing a service oriented architecture is that they donāt re-architect their current architecture to become service oriented. Iāve never really understood what they meant by that until I read <a href="http://blogs.msdn.com/nickmalik/archive/2007/08/07/getting-away-from-request-and-response-soa.aspx">this article</a>. SOA is not about adding a service based call to expose <strong>your current</strong> procedure calls as a service - itās so much more. Itās about enabling ease of change and to create a more agile architecture.</p>
<blockquote>Each of these assumptions exist in a Remote Procedure Call. They are forms of coupling, pure and simple. They fly in the face of SOA.
>
> </blockquote>
<p>What do you think? Does it make sense in your world?</p>
XPathmania and XPath on TV!2007-08-03T08:08:46+00:00http://richardhallgren.com/xpathmania-and-xpath-on-tv<p>Iāve blogged about the Visual Studio extension <a href="http://www.codeplex.com/MVPXML/Release/ProjectReleases.aspx?ReleaseId=77">XPathmania</a> <a href="http://www.webhostingsearch.com/blogs/richard/reading-text-value-from-node-using-xpath-function-directly-in-biztalk-orchestrations/">before</a>. Itās a very simple little tool that lets you write and test <a href="http://en.wikipedia.org/wiki/XPath">XPath</a> inside of Visual Studio 2005. No big deal if you already have tools like <a href="http://www.altova.com/products/xmlspy/xml_editor.html">XMLSpy</a> or <a href="http://www.microsoft.com/downloads/details.aspx?familyid=72d6aa49-787d-4118-ba5f-4f30fe913628&displaylang=en">XML Notepad</a> but still. I like not having to start another application, opening the XML document Iām working with and so on. Doing stuff inside of Visual Studio just feels right and saves some time anyway.</p>
<p>One of the <a href="http://www.dnrtv.com/default.aspx?showNum=67">last episodes</a> of <a href="http://www.dnrtv.com/">dnrTV</a> hosted <a href="http://donxml.com/Default.aspx">Dom Demsak</a> (Don XML), the creator of XPathmania. The show is 30% about XPathmania and 70% about XPath and XPath syntax in general. Itās kind of basic XPath but I think it can be useful for someone who feels they havenāt got full control of the language.</p>
<p>During the show they touch on <a href="http://www.w3schools.com/xml/xml_namespaces.asp">XML namespaces and XML default namespaces</a>. However they donāt really explain the difference between them and how it effects the document. Something thatās sad as I feel that XML namespaces (and especially default namespaces) is something that most people havenāt fully understood.</p>
<p>Anyway, if you got some spare time watch it or forward it someone you think should watch it. ;)</p>
Transform and split messages using an Xslt transformation pipeline component and the XmlDissasembler2007-08-02T08:44:09+00:00http://richardhallgren.com/transform-and-split-messages-using-an-xslt-transformation-pipeline-component-and-the-xmldissasembler<p>There was a question on the <a href="http://www.microsoft.com/technet/community/newsgroups/dgbrowser/en-us/default.mspx?dg=microsoft.public.biztalk.general">Microsoft newsgroup</a> the other day where someone had to split a message into parts. But some of the information that was supposed to go in to the different parts were part of the envelope. I thought Iād give my solution to the problem a try - here it is.</p>
<p>Say for example that we receive the following message.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">ns0:EmployeeSalesReport </span><span style="color: #FF0000; ">ReportID</span><span style="color: #0000FF; ">="R100"</span><span style="color: #FF0000; "> EmployeeID</span><span style="color: #0000FF; ">="0012345"</span><span style="color: #FF0000; "> xmlns:ns0</span><span style="color: #0000FF; ">="http://Example.TransformAndSplit.EmployeeSalesReport"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Sales</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ns1:Sale </span><span style="color: #FF0000; ">xmlns:ns1</span><span style="color: #0000FF; ">="http://Example.TransformAndSplit.Sale"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ItemID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">100</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ItemID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Amount</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">10</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Amount</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ns1:Sale</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ns1:Sale </span><span style="color: #FF0000; ">xmlns:ns1</span><span style="color: #0000FF; ">="http://Example.TransformAndSplit.Sale"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ItemID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">200</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ItemID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Amount</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">20</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Amount</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ns1:Sale</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Sales</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ns0:EmployeeSalesReport</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>In the above message we have different sales information from one employee <strong>but all the global employee and report information (the <em>ReportID</em> and <em>EmployeeID</em> attributes) exists in the root node</strong> (what weāll call the <em>envelope</em> of the message).</p>
<p>What we like to achieve is to split this envelope message into itās different sale item so we get separate message looking something like the below where each item contains the global information from the envelope.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">Sale </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">="http://Example.TransformAndSplit.Sale"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ItemID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">200</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ItemID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Amount </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">20</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Amount</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">EmployeeID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">0012345</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">EmployeeID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ReportID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">R100</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ReportID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Sale</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>There might be different needs for doing this in a pipeline but much of it comes down to choice of architecture style in your BizTalk solution. Personally Iād refuse to introduce another orchestration for splitting a message like this. I donāt believe thatās what orchestrations are for (they should deal with possible logic and workflow in my world). Iām sure other people feel different - feel free to use the comments.</p>
<h2 id="step-1---transforming-the-envelope-message-using-xslt">Step 1 - Transforming the envelope message using XSLT</h2>
<p>The first thing weāll need to do is to transform the envelope message so that the information from the root node (the <em>ReportID</em> and the <em>EmployeeID</em>) get into every single _Sale-_node. There are a couple of ways of achieving this but Iāll use the <a href="http://msdn2.microsoft.com/en-us/library/aa561389.aspx">XSLT-transformation pipeline component</a> that ships with the BizTalk 2006 SDK.</p>
<p>All this component does is to let you point out a <a href="http://en.wikipedia.org/wiki/XSLT">XSLT stylesheet</a> you like to use to transform your message.</p>
<p><a href="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6xsltpipeline29.jpg"><img src="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6xsltpipeline-thumb9.jpg" alt="" /></a></p>
<p>The stylesheet Iāve used is part of the solution that you can download here. I will not show the stylesheet full script here but rather the result after the message travel through the component.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><?</span><span style="color: #FF00FF; ">xml version="1.0" encoding="utf-8"</span><span style="color: #0000FF; ">?></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">EmployeeSalesReport </span><span style="color: #FF0000; ">EmployeeID</span><span style="color: #0000FF; ">="0012345"</span><span style="color: #FF0000; "> ReportID</span><span style="color: #0000FF; ">="R100"</span><span style="color: #FF0000; "> xmlns</span><span style="color: #0000FF; ">="http://Example.TransformAndSplit.EmployeeSalesReport"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Sales </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Sale </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">="http://Example.TransformAndSplit.Sale"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ItemID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">100</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ItemID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Amount </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">10</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Amount</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">EmployeeID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">0012345</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">EmployeeID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ReportID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">R100</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ReportID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Sale</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Sale </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">="http://Example.TransformAndSplit.Sale"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ItemID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">200</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ItemID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Amount </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">20</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Amount</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">EmployeeID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">0012345</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">EmployeeID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ReportID </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">=""</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">R100</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ReportID</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Sale</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Sales</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">EmployeeSalesReport</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>Ok, nice. Now we have all the information we like in each of the <em>Sale</em>-nodes! All we have to do now is to split the message!</p>
<h2 id="step-2---splitting-the-message">Step 2 - Splitting the message</h2>
<p>Weāll use the standard <a href="http://msdn2.microsoft.com/en-us/library/ms964545.aspx"><em>XmlDisassembler</em></a> component for splitting the message. All we have to do is to make sure we done the following.</p>
<ol>
<li>
<p>Set the schema envelope property to ā<strong>trueā</strong> in the schema editor.</p>
</li>
<li>
<p>Set the <em>Body Xpath</em> property on the _EmployeeSalesReport-_node to point to the _Sale-_node.</p>
</li>
<li>
<p>Configure the <em>Document Schemas _and</em> Envelope Schemas (<em>same properties are called _DocumentSpecNames</em> and <em>EnvelopeSpecNames</em> if your doing the configuration after deployment in the administration console_)_ properties of the <em>XmlDisassember</em> component to match the names of your schemas.</p>
</li>
</ol>
<p>This is what the envelope schema looks like in this example.</p>
<p><a href="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6envelopeschema59.jpg"><img src="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6envelopeschema-thumb19.jpg" alt="" /></a></p>
<p>This is what the <em>XmlDisassembler</em> configuration looks like.</p>
<p><a href="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6pipelineconfig29.jpg"><img src="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6pipelineconfig-thumb9.jpg" alt="" /></a></p>
<p>There, weāre done! Now we can drop a test file containing two <em>Sale</em>-nodes and all the report/employee information on the top and have the two following separate files as a result when using a file send port.</p>
<p><a href="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6out29.jpg"><img src="../assets/2007/08/windowslivewritertransformandsplitmessagesusinganxslttrab-f7f6out-thumb9.jpg" alt="" /></a></p>
<h2 id="setting-up-the-test-solution">Setting up the test solution</h2>
<ol>
<li>
<p><a href="http://www.richardhallgren.com/blogfiles/Example.TransformAndSplit.zip">Download</a> a zipped version of the solution.</p>
</li>
<li>
<p>Youāll have to unzip the project to <em>C:\Example.TransformAndSplit</em>. If that isnāt possible youāll have to change the path to the XSLT stylesheet in the <em>XsltComponent</em> in the pipeline as this is a fixed path.</p>
</li>
<li>
<p>When you build the <em>XsltComponent</em> the <em>Output path</em> is set to the <em>Pipeline Components</em> folder. This assumes that BizTalk is installed at _C:\Program Files\Microsoft BizTalk Server 2006_. If that isnāt the case make sure to change the output path of the component.</p>
</li>
<li>
<p>If youād like to run the pipeline component in debug Iāve set this up using the <a href="http://msdn.microsoft.com/library/en-us/sdk/htm/ebiz_sdk_utils_pipeline_ackm.asp?frame=true">pipeline.exe tool.</a> There are however some paths in the debug setting of the <em>XsltComponent</em> project also that assumes that your BizTalk solutions is installed at <em>C:\Program Files\Microsoft BizTalk Server 2006. _If this isnāt the case youāll have to change some values in the _Command lines arguments</em> property, but that only if you like to run debug.</p>
</li>
<li>
<p>Build and deploy.</p>
</li>
<li>
<p>Set up a receive port and location using the <em>TransformAndSplitSales</em> pipeline.</p>
</li>
<li>
<p>Set up a send port with for example a filter on the name of the <em>Receiveport</em> youāve just set up.</p>
</li>
<li>
<p>Drop the example message thatās part of the solution!</p>
</li>
</ol>
<h2 id="final-thoughts">Final thoughts</h2>
<p>This example didnāt really take much more than an hour to put together. I do however realize that this is a simplified incoming message and that in the case of a more complex message weād get a messy XSLT stylesheet to maintain. Itās also important to remember that using this method with XSLT transformation means that we will load the entire incoming Xml document into memory, so when weāre dealing with bigger Xml documents weāll have manipulate the incoming message using other techniques.</p>
<p>Hope this is useful for someone!</p>
Developing and debugging orchestrations using DebugView and SOAPTrace tools2007-07-31T07:38:33+00:00http://richardhallgren.com/developing-and-debugging-orchestrations-using-debugview-and-soaptrace-tools<p>The main problem I have with developing BizTalk orchestrations is the fact that Iām so blind when it comes to follow the runtime processing. Using the <a href="http://msdn2.microsoft.com/EN-US/library/aa577988.aspx">debugger</a> that is part of the HAT tool is slow and clumsy which IMHO makes the tool almost useless in everyday development. But there is hope!</p>
<h2 id="debugview">DebugView</h2>
<p><a href="http://www.microsoft.com/technet/sysinternals/default.mspx">Sysinternals</a> (<em>Windows Sysinternal</em> now - Microsoft bought them last year) <a href="http://www.microsoft.com/technet/sysinternals/Miscellaneous/DebugView.mspx">DebugView</a> is a wonderful little tool and is especially useful when it comes to figure out whatās actually going on inside an orchestration. Basically the tool listens to system wide debug output. From an orchestration itās possible to write debug information using the .NET <em><a href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.aspx">System.Diagnostics</a></em> namespace and the <a href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.debug.aspx"><em>Debug</em></a> or <em><a href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.trace.aspx">Trace</a></em> class.</p>
<h3 id="decide-on-how-to-filter">Decide on how to filter</h3>
<p>There are a couple of handy little tricks that makes DebugView a even better in BizTalk development. First one should try and have something in the debug messages that makes it possible to filter and distinct oneās own (as DebugView listens system wide debug output all running applications debug info will show up). Our team decided on ā<a href="http://www.sogeti.com">Sogeti</a>ā (our company name) for all our development and to have a method in our BaseLibrary component that outputs something like the below (the BaseLibrary is a small little .NET component with a couple of very useful classes we use company wide in our BizTalk related development).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; ">System.Diagnostics.Debug.WrtieLine(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Sogeti, your debug/trace message here</span><span style="color: #000000; ">"</span><span style="color: #000000; ">)</span></div>
</code></pre></div></div>
<p>This make is possible to have a filter in DebugView and to for example have it look something like this.</p>
<p><a href="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1debugview133.jpg"><img src="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1debugview1-thumb13.jpg" alt="" /></a></p>
<h3 id="trace-full-context-of-messages">Trace full context of messages</h3>
<p>Another little useful trick is to trace the full context of messages. This is done be storing the message in a <em>XmlDocument</em> typed variable and get the <em>OuterXml</em> property of that variable. The below code is and example of this.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; ">tempXml </span><span style="color: #000000; ">=</span><span style="color: #000000; "> msgFindPartyRequest.parameters;
System.Diagnostics.Trace.Write(System.String.Concat(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Sogeti, msgFindPartyRequest: </span><span style="color: #000000; ">"</span><span style="color: #000000; ">, tempXml.OuterXml));</span></div>
</code></pre></div></div>
<p>Example of a full message trace.</p>
<p><a href="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1debugview253.jpg"><img src="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1debugview2-thumb13.jpg" alt="" /></a></p>
<h3 id="to-trace-or-debug---thats-the-question">To Trace or Debug - thatās the question</h3>
<p>As stated earlier both <em>System.Diagnostics.Debug</em> and <em>System.Diagnostics.Trace</em> has methods (<em>Write</em>, <em>WriteLine</em> and so on) for outputting debug information. However there is only one that stays in your compiled code when switching from Development to Deployment compilation mode (guess which one ;)). So make sure you choose the right class for the right information. I like to have some critical messages left using Trace and be able to trace these even on the test and production server.</p>
<h3 id="debugview-on-a-remote-desktop">DebugView on a remote desktop</h3>
<p>When running DebugView on an other server (say a test or a production server) using <a href="http://www.microsoft.com/windowsxp/downloads/tools/rdclientdl.mspx">Remote Desktop</a> Iāve found that ones has to use the <a href="http://firechewy.com/blog/archive/2005/10/18/926.aspx">console user</a> on the server. This kind of makes sense as if weāre connection ānormallyā weāre creating a virtual session and thatās not were the debug information is written to.</p>
<h2 id="microsoft-soap-toolkit-30">Microsoft SOAP Toolkit 3.0</h2>
<p>This is a totally <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=C943C0DD-CEEC-4088-9753-86F052EC8450&displaylang=en">other tool</a> than DebugView but I thought it fit here any way. Itās a handy tool when working with SOAP based messages. Without itās very hard to actually figure out how the raw request and response message look and why your orchestration web service is acting the way it does.</p>
<p><a href="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1soaptrace123.jpg"><img src="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1soaptrace1-thumb3.jpg" alt="" /></a></p>
<p>The trace tool is placed as a <a href="http://en.wikipedia.org/wiki/Reverse_proxy">reverse proxy</a> between BizTalk and the Internet. Itās setup by telling the tracing tool which localhost port to listen at (for example 9091 as in the example below) then weāll redirect to that port by changing the setting in the BizTalk send port.</p>
<p><a href="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1soapsendport122.jpg"><img src="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1soapsendport1-thumb2.jpg" alt="" /></a></p>
<p>Finally weāll set up the trace tool to listen to port 9091 and redirect all traffic to our web service URL at port 80 in this case. So basically the trace tool will catch all the traffic hitting the 9091 port and forward it.</p>
<p><a href="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1soaptrace222.jpg"><img src="../assets/2007/07/windowslivewriterdevelopinganddebugingorchestrationsusing-dfd1soaptrace2-thumb2.jpg" alt="" /></a></p>
<p>Thatās it! This is probably basic stuff for most of you but hopefully itās useful for someone!</p>
<p>Iāve also noticed that the SOAP Toolkit is deprecated by Microsoft and Iād like to hear if anyone used something else (like <a href="http://www.fiddlertool.com/fiddler/">Fiddler</a> example) for tracing SOAP messages. Iād also love some other tips, tools and methods you use for debugging BizTalk orchestrations.</p>
Reading text value from node using XPath function directly in BizTalk orchestrations2007-07-24T14:10:02+00:00http://richardhallgren.com/reading-text-value-from-node-using-xpath-function-directly-in-biztalk-orchestrations<p>The XPath function thatās available directly inside BizTalk orchestration is a powerful little tool. However Iāve seen a couple of project where developers just grown tired of it and started creating their own little libraries instead. Iāll be the first to admit that the XPath function isnāt perfect, and it sure doesnāt work like most of the other XPath engines (which is the biggest problem) but itās still <strong>inside</strong> the orchestration and you can use it to both read and <a href="http://msdn2.microsoft.com/en-us/library/ms963270.aspx">assign values</a> to a message which is super useful! <strong>Basically I donāt see a valid reason for bringing more complexity into your solution by adding another library</strong> - as long as youāre just going to read or set value using XPath.</p>
<p>However there is one trick that you should know of when it comes to reading a text value from a node. Basically you have to use both the <a href="http://msdn2.microsoft.com/en-us/library/ms256180.aspx">string()</a> and <br />
text() XPath functions. Both <a href="http://geekswithblogs.net/cyoung/archive/2006/12/12/100981.aspx">Charles Young</a> and <a href="http://www.sabratech.co.uk/blogs/yossidahan/2006/09/returning-text-only-from-xpath-in.html">Yossi Dahan</a> has good post on this subject. Also if your new to writing XPath expressions for complex schemas with loads of namespaces and stuff (like schemas in BizTalk) <a href="http://www.webhostingsearch.com/blogs/richard/nevermind-the-xml-namespaces-in-xpath-expressions/">this post</a> could be useful for you.</p>
<p>Finally a nice tool for writing and testing small XPath expression inside Visual Studio (if you donāt want to spend x minutes waiting for XmlSpy to start up ā¦) is <a href="http://www.codeplex.com/MVPXML/Release/ProjectReleases.aspx?ReleaseId=4894">XPathmania</a>. Read about it <a href="http://donxml.com/allthingstechie/archive/2006/07/07/2792.aspx">here</a> - I use it all the time!</p>
Lists, Arrays and collections within BizTalk orchestrations2007-07-05T12:40:30+00:00http://richardhallgren.com/lists-arrays-and-collections-within-biztalk-orchestrations<blockquote>
>
> **Update 2012-03-28**
Unfortunately the images for this post was lost in upgrade of the blog.
>
> </blockquote>
<p>This post shows how itās possible to create your own .NET class and then use this within your orchestration (as a variable) to work with typed lists - something that unfortunately isnāt supported out of the box in BizTalk orchestrations. Below is the class used to create a typed list for System.String objects.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">namespace</span> Sample.BizTalkCollections
{
[Serializable]
<span class="kwrd">public</span> <span class="kwrd">class</span> StringList
{
<span class="kwrd">private</span> List<<span class="kwrd">string</span>> _list = <span class="kwrd">new</span> List<<span class="kwrd">string</span>>();
<span class="kwrd">public</span> <span class="kwrd">void</span> Add(<span class="kwrd">string</span> item)
{
_list.Add(item);
}
<span class="kwrd">public</span> <span class="kwrd">int</span> Count()
{
<span class="kwrd">return</span> _list.Count;
}
<span class="kwrd">public</span> <span class="kwrd">bool</span> Remove(<span class="kwrd">string</span> item)
{
<span class="kwrd">return</span> _list.Remove(item);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> RemoveAt(<span class="kwrd">int</span> index)
{
_list.RemoveAt(index);
}
<span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString()
{
StringBuilder builder = <span class="kwrd">new</span> StringBuilder();
<span class="kwrd">foreach</span> (<span class="kwrd">string</span> item <span class="kwrd">in</span> _list)
{
builder.AppendLine(item);
}
<span class="kwrd">return</span> builder.ToString();
}
}
}
</code></pre></div></div>
<p>Notice that the class is <a href="http://msdn2.microsoft.com/en-us/library/system.serializableattribute.aspx">serializable</a> so BizTalk can serialize when <a href="http://msdn2.microsoft.com/en-us/library/aa995563.aspx">dehydrating the orchestration</a> to the database. Weāve also chosen not to extend the <a href="http://msdn2.microsoft.com/en-us/library/system.collections.ilist.aspx">IList interface</a> as we donāt want to expose all methods of that interface, but only the once weāll really going use within our orchestrations.</p>
<p>This <em>StringList</em> class exists within the <em>BizTalkCollections</em> namespace where we have other classes for lists types with different datatypes (for example <em>ObjectList</em>, <em>Int32List</em> and so on). Below is a picture showing the structure of the Visual Studio project containing all the collections we current have implemented. This project and the BizTalk testproject is available for <a href="http://www.richardhallgren.com/blogfiles/Sample.BizTalkCollection.zip">download here</a>.</p>
<p><a href="../assets/2007/07/windowslivewriterlistsarraysandcollectionswithinorchestra-b729biztalkcollections23.jpg"><img src="../assets/2007/07/windowslivewriterlistsarraysandcollectionswithinorchestra-b729biztalkcollections-thumb23.jpg" alt="" /></a></p>
<p>In the orchestration we then have set up a variable and type this to our <em>StringList</em> class within the <em>Sample.BizTalkCollections</em> namespace.</p>
<p><a href="../assets/2007/07/windowslivewriterlistsarraysandcollectionswithinorchestra-b729variable53.jpg"><img src="../assets/2007/07/windowslivewriterlistsarraysandcollectionswithinorchestra-b729variable-thumb53.jpg" alt="" /></a></p>
<p>Also make sure the assembly with your collection class is installed in the <a href="http://support.microsoft.com/kb/815808">GAC</a>, otherwise youāll end up with a _FileNotFound exception _saying</p>
<blockquote>
>
> Could not load file or assembly 'Sample.BizTalkCollections, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7109528d5dbf986b' or one of its dependencies. The system cannot find the file specified.
>
>
</blockquote>
<p>Then you can use the following code within your orchestration! <a href="http://www.richardhallgren.com/blogfiles/Sample.BizTalkCollection.zip">Download the sample project</a> and test it.</p>
<p><a href="../assets/2007/07/windowslivewriterlistsarraysandcollectionswithinorchestra-b729code212.jpg"><img src="../assets/2007/07/windowslivewriterlistsarraysandcollectionswithinorchestra-b729code2-thumb12.jpg" alt="" /></a></p>
<h2 id="a-really-generic-class">A really generic class</h2>
<p>Iād really like for it be possible to create my own generic classes and then initialize these using something like the below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>genericList = Sample.BizTalkCollections.GenericList<System.String>();
</code></pre></div></div>
<p>However this isnāt possible as BizTalk orchestrations donāt seem to understand generic classes ā¦ If someone found a solution to this please let me/us know via the comments to this post.</p>
TechEd Barcelona here I come!2007-07-02T11:41:34+00:00http://richardhallgren.com/teched-barcelona-here-i-come<p>Iāve just found out that I get to go to <a href="http://www.mseventseurope.com/teched/">TechEd in November</a>! I havenāt been there before. Iāve been to a lot of conferences but not **the **Microsoft conference. Do I have to say that Iām looking forward to it?</p>
<p>If youāre going and feel like meeting up for a BizTalk lunch, dinner or whatever donāt hesitate to drop me an e-mail.</p>
Reading the message body and context from the BizTalkDTADb using operations library in BizTalk 20062007-06-04T14:18:20+00:00http://richardhallgren.com/reading-the-message-body-and-context-from-the-biztalkdtadb-using-operations-library-in-biztalk-2006<p><strong>Update 2007-07-05:</strong> The example project used in the post can be <a href="http://www.richardhallgren.com/blogfiles/BizTalkDTAReader.zip">downloaded from here</a>.</p>
<p>The operations dll (<em>Micrsoft.BizTalk.Operations</em>) is one of the new bits in BizTalk 2006 that at least I havenāt heard much about (most of you probably find in the <em>C:\Program Files\Microsoft BizTalk Server 2006</em> folder). However itās a library with a lot of useful functionality.</p>
<p>In this post Iāll focus on how itās possible to use the library to get hold of message parts and message context from the BizTalk tracking database (usually called the <em>BizTalkDTADb</em>). If youāre unfamiliar with the architecture of the tracking in BizTalk <a href="http://msdn2.microsoft.com/en-us/library/aa559554.aspx">this article</a> is a good place to start.</p>
<h2 id="what-used-to-be-the-problem">What used to be the problem?</h2>
<p>In BizTalk 2004 one soon got into problems when trying to read the message parts and the message context from the tracking database. The problem is that the the Xml is compressed (something that makes totally sence - Xml is a perfect candidate for compression). To my knowledge no one has found a good way to decompress the message context. Thereās however a way to decompress <strong>the message parts</strong> (and only the parts) that <a href="http://groups.google.com/group/microsoft.public.biztalk.general/browse_thread/thread/599c038807317802">Rob posted on in the BizTalk newsgroup</a>. But this method doesnāt work on the compressed context of the same message that the parts belong to! One could assume that the same method could be used for both compression and decompression but I havenāt got it to work for the context of the message (read about my frustration <a href="http://groups.google.com/group/microsoft.public.biztalk.general/browse_thread/thread/19a232369218b2f9">here</a>)</p>
<h2 id="whats-wrong-with-wmi-and-msbts_trackedmessageinstance">Whatās wrong with WMI and <em>MSBTS_TrackedMessageInstance</em>?</h2>
<p>So the option that was left to us before BizTalk 2006 for reading all the message parts as well as the message context was to use the <a href="http://msdn2.microsoft.com/en-us/library/aa546797.aspx">MSBTS_TrackedMessageInstance WMI scrtipt</a> and save everything down to file. The problem with this approach is that itās slow and ugly! Say that we like to save a couple of thousand messages from the tracking database. When forced to save the messages to file weāll end up with a slow and ugly solution where writing to file takes ages, then we have to read the content of the different files before cleaning up and deleting the files.</p>
<h2 id="micrsoftbiztalkoperations-to-the-rescue">Micrsoft.BizTalk.Operations to the rescue</h2>
<p>A quick view in <a href="http://www.aisto.com/roeder/dotnet/">Lutz Roederās Reflector</a> shows us a couple of interesting methods in the operations dll. However Iāll only use the <em>GetTrackedMessage</em> method in this post.</p>
<p><a href="../assets/2007/06/operations1.jpg"><img src="../assets/2007/06/operations-thumb1.jpg" alt="operations" /></a></p>
<p>Iāve written a tiny test application that uses the library to read the body part of the message (the meat of the message) and a couple of properties Iām interested in from the context of the message. It looks something like this. If your interested drop me an email and Iāll send it. The first screenshot below shows an example of reading the <em>InterchangeID</em> from the context of a tracked message.</p>
<p><a href="../assets/2007/06/operationstest22.jpg"><img src="../assets/2007/06/operationstest2-thumb2.jpg" alt="OperationsTest2" /></a></p>
<p>This screenshot shows an example of reading the full body of a tracked message from the tracking database. Try doing this with less then 10 lines of code using the <em>MSBTS_TrackedMessageInstance</em> script!</p>
<p><a href="../assets/2007/06/operationstest11.jpg"><img src="../assets/2007/06/operationstest1-thumb1.jpg" alt="OperationsTest1" /></a></p>
<p>There is really nothing to the application, reading a tracked message using the <em>MessageID</em> will return an object implementing <em><a href="http://msdn2.microsoft.com/en-us/library/microsoft.biztalk.message.interop.ibasemessage_members.aspx">IBaseMessage</a></em> and we basically read the <em><a href="http://msdn2.microsoft.com/en-us/library/microsoft.biztalk.message.interop.ibasemessage.bodypart.aspx">BodyPart</a></em> property of - it really couldnāt be any easier.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">static</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">string</span><span style="color: #000000; "> GetMessageBodyByMessageID(</span><span style="color: #0000FF; ">string</span><span style="color: #000000; "> dbServer, </span><span style="color: #0000FF; ">string</span><span style="color: #000000; "> dbName, Guid messageID)
{
TrackingDatabase dta </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> TrackingDatabase(dbServer, dbName);
BizTalkOperations operations </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> BizTalkOperations();
IBaseMessage message </span><span style="color: #000000; ">=</span><span style="color: #000000; "> operations.GetTrackedMessage(messageID, dta);
</span><span style="color: #0000FF; ">string</span><span style="color: #000000; "> body </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">.Empty;
</span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">(StreamReader streamReader </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> StreamReader(message.BodyPart.Data))
{
body </span><span style="color: #000000; ">=</span><span style="color: #000000; "> streamReader.ReadToEnd();
}
</span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> body;
} </span></div>
</code></pre></div></div>
<p>Iād be very interested in how people use the operations library both when it comes to read and use tracked messages, but also in other ways! Use the comments to tell me and other readers how you use it your solutions!</p>
Visual Studio 2005 tries to load the .pdb debug file from the GAC2007-05-15T06:14:01+00:00http://richardhallgren.com/visual-studio-2005-tries-to-load-the-pdb-debug-file-from-the-gac<p>Ever seen this alert when trying to debug a project using Visual Studio 2005?</p>
<blockquote>The following module was build with optimizations enabled or without information:
>
> C:\Windows\assembly\GAC_MSIL\ ...
>
> To debug this module, change its build configuration to debug mode. TO suppress this message, disable the 'Warn if no user code on launch' debugger option.
>
> </blockquote>
<p>Basically this means that <strong>Visual Studio canāt find the debug file **(the <a href="http://msdn2.microsoft.com/en-us/library/ms241903.aspx">.pdb file</a>)</strong> at the same location as the dll is loaded from<strong>. Reading the error message tells us that the **dll been loaded from the GAC</strong> and there arenāt any pdb files there! Just make sure to uninstall the dll from the GAC and Visual Studio should be able to load it from your Debug folder and youāll probably be good to go.</p>
XPathUpdateException when assigning value to constructed messages2007-05-14T14:11:53+00:00http://richardhallgren.com/xpathupdateexception-when-assigning-value-to-constructed-messages<p>Ever had a āuse of unconstructed messageā error message in your orchestrations? Then you know that messages has to be constructed before one can use them within orchestrations. Basically messages in orchestrations are created in ports or when executing a map in a construct shape. However there is also the possibility of creating messages in expression shapes using code. Matt Meleski does a great job explain the different approaches in his <em><a href="http://objectsharp.com/cs/blogs/matt/archive/2004/11/09/1009.aspx">Constructing BizTalk 2004 XML Messages (In an Orchestration) - Choices</a></em> blog post_._</p>
<p>However there are some pitfalls when constructing messages from scratch within orchestration (a part from the fact that there really isnāt a clean way of doing it ā¦ Scott Colestock has some ideas in <a href="http://www.traceofthought.net/PermaLink,guid,c1164c59-72e2-49e2-be7a-47e4e8dc46d4.aspx">this post</a>).</p>
<p>A common problem is <em>XPathUpdateException</em>. Say one has a mapping that looks like the one below where one node isnāt mapped. <strong>This will create a message without the <em>ElementB</em> element</strong>. This doesnāt have to be in a mapping, it could also happend when constructing a message using code in a expression shape. A common scenario is that we <strong>add code for constructing the bone structure of the XML message</strong>, then change the schema <strong>without updating the construct code. Ergo a message will be constructed without that element</strong> (could be both valid or invalid XML then depending on the <em>Min Occurs</em> value)!</p>
<p><a href="../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2complexmapping23.jpg">[](../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2complexmapping23.jpg)</a><a href="../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2complexmapping61.jpg"><img src="../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2complexmapping-thumb61.jpg" alt="" /></a></p>
<p>When we then try to add a value to the element that hasnāt been created the exception will be thrown!</p>
<p><a href="../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2assignment31.jpg"><img src="../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2assignment-thumb31.jpg" alt="" /></a></p>
<p>One way around when using a map is to make sure to have a default value on every element to force them be constructed. Adding the following to map will make it work.</p>
<p><a href="../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2defaultvalue61.jpg"><img src="../assets/2007/05/windowslivewriterxpa.setdistinguishedfieldwhileassigningv-ceb2defaultvalue-thumb61.jpg" alt="" /></a></p>
<p>Itās a one time mistake but itās good to know what to look for when the <em>XPathUpdateException in Microsoft.XLANGs.Core.XSDPart.SetDistinguishedField</em> (if itās a distinguished field that is) shows up in the event log.</p>
Whatās an ESB architecture!?2007-05-11T06:18:39+00:00http://richardhallgren.com/whats-an-esb-architecture<p>Iāve just finished reading a <a href="http://www.neudesic.com/media/Neudesic%20-%20Neuron%20ESB%20White%20Paper%20(P1).pdf">paper written by David Pallmann</a> (PDF) from <em><a href="http://www.neudesic.com/">Neudesic</a></em>. Belive it or not (or even better check it out), itās a short and understandable description of what an ESB is!</p>
<p><em>Neudesic</em> sells a product called <em><a href="http://www.neudesic.com/Main.aspx?SS=7&PE=75">Cyclone</a></em> which is something they call a <em>ESB architecture and framework software</em> and even if describing this product is the main purpose of the paper the first part deals with describing the basics of an ESB and tryās to āassemble a synthesis of popular ESB definitionsā.</p>
<p>Iāve chosen a couple of parts of the paper that really appealed to me but I really recommend the full length version (only 8 pages!).</p>
<blockquote>Defining the ESB
>
> * An ESB is a backbone for connecting and integrating an enterpriseās applications and services.
> * An ESB provides the necessary infrastructure to create a service oriented architecture.
> * An ESB is a convergence of EAI, MOM, and SOA concepts.
> * An ESB is based on open standards such as XML, SOAP, and WS-*.
> * An ESB provides intelligent routing, such as publish-subscribe, message brokering, and failover routing.
> * An ESB provides mediation, overcoming data, communication, and security differences between endpoints.
> * An ESB integrates with legacy systems using standardsbased adapters.
> * An ESB provides logical centralized management but is
physically decentralized.
> * An ESB is able to apply EAI concepts such as rules and
orchestrations.
> * An ESB is able to monitor and throttle activity as per a Service Level Agreement (SLA).
> </blockquote>
<p>I never thought of an ESB as an convergence of EAI (Enterprise Application Integration), MOM (Message Oriented Middleware) and SOA (Service Oriented Architecture) concepts. But, ok, so what does the writer really mean by these concepts?</p>
<blockquote>SOA makes loosely-coupled, decentralized solutions possible that are enterprise-ready and based on interoperable standards. EAI allows integration of any combination of systems, with sophisticated message brokering, message translation, business process orchestration, and rules engine processing. MOM provides intelligent routing such as publish-subscribe topical messaging and strong managerial controls over routing, auditing, activity monitoring, and throttling.
>
> </blockquote>
<p>And why do we need a bus architecture on top of SOA, MOM and EAI?</p>
<blockquote>Point-to-point architecture
works all right on a small scale, but its problems become
apparent when used at the enterprise level. If each system has to know the connection details of every other system, then each new system added increases the problem of configuration and management exponentially. This was the impetus that led us to hub-and-spoke architectures, which most EAI products use. This architecture was a vast improvement over point-to-point architectures, and each system needed to communicate with only the hub. In addition, the hub could provide excellent management features since it was a party to all communication. It only took time to reveal some shortcomings with the hub-and-spoke approach, and today it is often associated with concerns about scalability, single point of failure, and vendor lock-in.
>
> ...
>
> Fortunately, there is a sound compromise to be found in the bus architecture, which provides the benefits of logical centralization but is physically decentralized. The bus architecture in earlier days was often used in message bus systems based on proprietary technologies, but an ESB implements this architecture using WS-* standards.
>
> </blockquote>
<p>So using all three of them will make an ESB? Well, not really ā¦</p>
<blockquote>If combining disciplines was all there was to an ESB, weād simply call it āconsultingā. To properly leverage these disciplines they need to be combined in the right way through an architecture that lets their strengths shine and overcome their inherent weaknesses. Each discipline has some weak areas that the others help to resolve: SOA needs better enterprise manageability; EAI needs to become decentralized; MOM needs to get away from proprietary technologies. Combining these disciplines properly in an ESB overcomes these weaknesses.
>
> </blockquote>
<p>Iād be very intreseted in comments of other artciles, papers and so on relating to the ESB concept!</p>
Get row identity from SQL Adapter response2007-04-18T14:11:52+00:00http://richardhallgren.com/get-row-identity-from-sql-adapter-response<p>Recently I had to insert a record using a stored procedure and the SQL Adapter in BizTalk 2006. There are lots of examples on both how to insert records and how to select a number of record using this adapter. However I had problems finding how to **insert a record and receiving the new id of the inserted row in return **(the <em><a href="http://msdn2.microsoft.com/en-us/library/ms190315.aspx">SCOPE_IDENTITY()</a></em>). In my scenario I needed the id to insert into another database further down in the orchestration.</p>
<p>I ended up with a stored procedure looking like the below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; ">ALTER</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">PROCEDURE</span><span style="color: #000000; "> </span><span style="color: #FF0000; ">[</span><span style="color: #FF0000; ">dbo</span><span style="color: #FF0000; ">]</span><span style="color: #000000; ">.</span><span style="color: #FF0000; ">[</span><span style="color: #FF0000; ">TestInsertParty</span><span style="color: #FF0000; ">]</span><span style="color: #000000; ">
</span><span style="color: #008000; ">@partyName</span><span style="color: #000000; "> </span><span style="color: #000000; font-weight: bold; ">nchar</span><span style="color: #000000; ">(</span><span style="color: #800000; font-weight: bold; ">30</span><span style="color: #000000; ">) </span><span style="color: #808080; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">NULL</span><span style="color: #000000; ">
</span><span style="color: #0000FF; ">AS</span><span style="color: #000000; ">
</span><span style="color: #0000FF; ">BEGIN</span><span style="color: #000000; ">
</span><span style="color: #0000FF; ">SET</span><span style="color: #000000; "> NOCOUNT </span><span style="color: #0000FF; ">ON</span><span style="color: #000000; ">;
</span><span style="color: #0000FF; ">Insert</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">Into</span><span style="color: #000000; "> Party (</span><span style="color: #FF0000; ">[</span><span style="color: #FF0000; ">name</span><span style="color: #FF0000; ">]</span><span style="color: #000000; ">, chain_idx) </span><span style="color: #0000FF; ">Values</span><span style="color: #000000; ">(</span><span style="color: #008000; ">@partyName</span><span style="color: #000000; ">, </span><span style="color: #0000FF; ">NULL</span><span style="color: #000000; ">)
</span><span style="color: #0000FF; ">Select</span><span style="color: #000000; "> </span><span style="color: #FF00FF; ">Scope_Identity</span><span style="color: #000000; ">() </span><span style="color: #0000FF; ">As</span><span style="color: #000000; "> Id </span><span style="color: #0000FF; ">For</span><span style="color: #000000; "> Xml </span><span style="color: #000000; font-weight: bold; ">Raw</span><span style="color: #000000; "> (</span><span style="color: #FF0000; ">'</span><span style="color: #FF0000; ">Response</span><span style="color: #FF0000; ">'</span><span style="color: #000000; ">)
</span><span style="color: #0000FF; ">END</span></div>
</code></pre></div></div>
<p>The trick was to use the <a href="http://msdn2.microsoft.com/en-us/library/ms175140.aspx"><em>XML RAW Mode</em></a>. This mode transforms the result set into a generic identifier as _<row>_. It is however possible to provide a element name, as <_Response>_. Basically this will insert the new value and return something like this from the stored procedure.</_Response></row></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">Response </span><span style="color: #FF0000; ">Id</span><span style="color: #0000FF; ">="1054"</span><span style="color: #FF0000; "> </span><span style="color: #0000FF; ">/></span></div>
</code></pre></div></div>
<p>After return via the send port the orchestration will receive something like the below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">TestInsertResponse </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">="TestInsert"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Response </span><span style="color: #FF0000; ">Id</span><span style="color: #0000FF; ">="1054"</span><span style="color: #FF0000; "> </span><span style="color: #0000FF; ">/></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">TestInsertResponse</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>The schema that I use to both handling the response and request against the SQL Adapter is shown below. First I set the type of the Id-attribute to <em>xs:int</em> but this gave me some problems when using the promoted value in the orchestration, everything worked fine when switching back to <em>xs:string</em>.</p>
<p><a href="http://richardhallgren.com/blog/wp-content/uploads/2007/04/WindowsLiveWriter/GetrowidentityfromSQLAdapterresponse_D964/sqlinsertschema%5B12%5D2.jpg"><img src="http://richardhallgren.com/blog/wp-content/uploads/2007/04/WindowsLiveWriter/GetrowidentityfromSQLAdapterresponse_D964/sqlinsertschema_thumb%5B12%5D2.jpg" alt="" /></a> <br />
The same technique would be used for receiving a code from the stored procedure (say 1 for success and 0 for failure or whatever) and then to make a logical decision in the orchestration.</p>
Convoying2007-04-05T07:21:51+00:00http://richardhallgren.com/convoying<p>Convoying is one of BizTalkās real strengths but it has a lot of pitfalls (Iām talking performance, zombies etc). <a href="http://msdn2.microsoft.com/en-us/library/ms942189.aspx">This article</a> is really good at explaining the different patterns used for creating convoys. It also makes some deep dives into how the subscriptions are solved, why zombies are created and how to deal with them.</p>
<p>Even if you feel you understand the convoy patters from before the part about how BizTalk solves the subscriptions for correlations (the part called <em>Basic Convoy Theory</em>) is great.</p>
<p><strong>Using sequential convoy to handle ordered delivery</strong></p>
<p>A big selling point in BizTalk 2006 is itās ability to handle <a href="http://msdn2.microsoft.com/en-us/library/aa559637.aspx">Ordered Delivery</a>. Itās important however to understand that this setting (on the Receive and Send port) only works in a pure messaging scenario (a scenario without orchestration, just passing messages between ports). To get order delivery in a scenario using orchestrations one has to use the sequential convoy pattern (basically forcing the orchestration to only one instance on one thread). This <a href="http://msevents.microsoft.com/cui/webcasteventdetails.aspx?eventid=1032288276&culture=en-us">Webcast</a> explains this in depth and also deals with some of the different problems that are related to the issue. Problems like performance of course, but also the requirement for receive adapter (on the send side all adapters support ordered delivery) for enabling ordered delivery (youāll have to use MSMQ, MQSeries or specific scenarios of File, SOAP or HTTP).</p>
<p>Both convoying and ordered delivery are important concepts to understand in depth to be able to make the right decisions in a BizTalk 2006 solution.</p>
Weekly sum up2007-03-02T08:31:13+00:00http://richardhallgren.com/weekly-sum-up<p>Iāll start trying to post a weekly sum up of BizTalk, .NET topics Iāve come across during the week. Weāll see how goes as Iām not the most constant blogger ā¦</p>
<p>However I worked with mainly three things this week.</p>
<h3 id="error-handling-and-general-exception">Error handling and General Exception</h3>
<p>Iāve tested some ideas relating to an error handling pattern we like to implement in a one of our major integration projects. Weāve looked at how the new BizTalk 2006 <a href="http://msdn2.microsoft.com/en-us/library/aa578516.aspx">Failed Message Routing</a> fits in with our project. The idea is to have and Orchestration listening to the Error Message, log these and then put the failing message parts to file. Weāll then have a system that picks up the failed messages, launches them in an editor and makes it possible to resend the message after itās been edited.</p>
<p>Problem arises when we get to handling exceptions in Orchestrations. Orchestrations doesnāt have the possible to use Failed Message Routing as ports does (I guess that ok, we might want handle different errors in different ways and so on.). However that means that we have to catch an error and create our own Error Message to submit to the message data box for further routing to the Orchestration handling errors (the one that logs and puts the message to file.) So far so good as long as we donāt get an <a href="http://geekswithblogs.net/cyoung/archive/2004/04/26/4345.aspx">General Exception</a>! Usually when getting an General Exception, and we donāt catch it, the message gets suspended and we get a some error details giving us an idea of what went wrong. However as soon as one catches a General Exception we loose all information about the error ā¦ Weāve still havenāt found a good way of handling these errors. We just canāt afford loosing that error information!</p>
<p>General Exceptions are still a mystery to me. I guess that are there so BizTalk has a chance in catching exception that arenāt raised from .NET based code. But what kind of errors within an orchestration raises these kind of exceptions? I know a failure in a mapping does, what else? Iād really like this scenario to better documented. The error handling patter is based on a chapter in the <a href="http://www.amazon.com/Pro-BizTalk-2006-George-Dunphy/dp/1590596994">Pro BizTalk 2006 book</a> (which is a excellent book in my opinion - buy it!) but the General Exception and how to deal with it isnāt discussed there either. <strong>Any ideas, book, articles are highly appreciated!</strong></p>
<h3 id="validation">Validation</h3>
<p>One important thing to think of in a BizTalk solution <strong>is to not let anything either in or out that doesnāt validate</strong> (ok, there are exception to this, but generally speaking)! BizTalk has great built in support for this in the <a href="http://msdn2.microsoft.com/en-us/library/aa578187.aspx">XML Validator Pipeline Component</a> (you might also want to have a look at <a href="http://thearchhacker.blogspot.com/2004/09/cool-xsd-validation-function-for.html">this code</a>). However when working with this itās important to understand what one is validating against and it suddenly even more important to understand every details in the schemas (external system owners usually like some technical explanation when your telling them that their messages donāt validate in your pipeline ;)). Things we run into this week is the <a href="http://www.w3.org/TR/xmlschema-0/#NS">elementFormDefault</a> attribute. The following reading help me understanding what the attribute does:</p>
<ul>
<li><a href="http://www.w3.org/TR/xmlschema-0/#NS">http://www.w3.org/TR/xmlschema-0/#NS</a></li>
<li><a href="http://www.hanselman.com/blog/XmlValidatingReaderProblemsOverDerivedXmlReaders.aspx">http://www.hanselman.com/blog/XmlValidatingā¦XmlReaders.aspx</a></li>
<li><a href="http://geekswithblogs.net/dmillard/archive/2004/10/20/12935.aspx">http://geekswithblogs.net/dmillardā¦12935.aspx</a></li>
<li><a href="http://blogs.msdn.com/ebattalio/archive/2006/03/03/543154.aspx">http://blogs.msdn.com/ebattalio/archive/2006/03/03/543154.aspx</a></li>
</ul>
<p>Another thing we ran into was white space handling and the <em>xml:space</em> attribute. Apparently if one likes to have a node with a space in it BizTalk removes this if the element doesnāt have the <em>xml:space</em> attribute. so <em><node> </node></em> will come out as <em><node></node></em> - sound familiar?</p>
<p>But if the schema doesnāt declare that the node will have a xml:space attribute the validation will fail! To get this working one has to get the schema declaring the the xml:space attribute and then reference it like <a href="http://www.jezuk.co.uk/cgi-bin/view/jez?id=2306">this example</a>. The schema from w3c (if you donāt write your own like in the article) is located <a href="http://www.w3.org/2001/xml.xsd">here</a>.</p>
<h3 id="end-to-end-tracing-in-a-soa">End-to-end tracing in a SOA</h3>
<p>Iāll make this short even if it should be the longest part in this post. Basically weāre trying to archive the following:</p>
<p>Our solution send loads of different messages types between five different BizTalk servers. The client likes to be able to have full text search within these messages and to also be able to see all the messages in each interchange within a server.</p>
<p>So say for example that we receive and <em>Order message</em> in a flat file format. This is transformed in to a Xml message that is then routed down to two other different BizTalk servers. It should then be possible for the client to start an application, click on the <em>Order message</em> type, enter for example the <em>order number</em> (an element i in the message) and see the the full content of the different files within the interchange (in this example that would be the flat file and the Xml file) where that <em>Order number</em> is found.</p>
<p>Basically itās does what the HAT does (with full text search and a custom GUI). In the first phase of the project weāll have it work per server, but in the final solution this should perform over all servers ā¦ Iāll come back to this in a later post. In the mean time listen to <a href="http://www.hanselminutes.com/default.aspx?showID=68">this episode of Hanselminutes on end-to-end tracking</a>. This will be a challenge in every service orientated architecture ā¦</p>
<h3 id="finally">Finally</h3>
<p>Iāve sold my <a href="http://www.apple.com/se/ipodnano/">iPod Nano</a> and ordered the <a href="http://www.creative.com/products/mp3/zenvisionm/">Creative Vision Zen:M</a>. Now Iāll catch up on all those <a href="http://www.dnrtv.com/">dnrTV Webcasts</a>! Iāll also make sure to watch everyone of the <a href="http://richardhallgren.com/blog/?p=25">BizTalk 2006 Webcasts</a> during my commute to work.</p>
<p>Let me know if you found some of this information useful and Iāll try harder to post some like this every Friday.</p>
Simple RegEx replace in C#2007-02-01T07:22:47+00:00http://richardhallgren.com/simple-regex-replace-in-c<p>As I donāt use regular expressions that often I always forget the syntax. So I thought I just put a basic replace pattern up here.</p>
<p>This method takes a schema, finds all places where is says <em>schemaLocation=āwhateverā</em> in a text and changes this to <em>schemaLocation=āwhatever<strong>.xsd</strong>ā</em> and then returns the schema.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; ">private</span><span style="color: #000000; "> XmlSchema FixSchemaLocation(XmlSchema schema)
{
System.Text.RegularExpressions.Regex locationReplacePattern </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> System.Text.RegularExpressions.Regex(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">schemaLocation=\"(?<location>.*?)\"</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);
</span><span style="color: #0000FF; ">string</span><span style="color: #000000; "> locationReplaceValue </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">"</span><span style="color: #000000; ">schemaLocation=\"${location}.xsd\"</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;
</span><span style="color: #008000; ">//</span><span style="color: #008000; ">Puts .xsd after the schemaLocation. We need this find the imported schemas</span><span style="color: #008000; ">
</span><span style="color: #000000; "> StringWriter sw </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> StringWriter();
schema.Write(sw);
XmlSchema formatedSchema </span><span style="color: #000000; ">=</span><span style="color: #000000; "> XmlSchema.Read(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> StringReader(locationReplacePattern.Replace(sw.ToString(), locationReplaceValue)),</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);
</span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> formatedSchema;
}</span></div>
</code></pre></div></div>
BizTalk assembly version redirection2007-01-26T13:34:56+00:00http://richardhallgren.com/biztalk-assembly-version-redirection<p>The version redirection in BizTalk do NOT work as one is used to coming from a ordinary .NET developer background (so I was wrong in <a href="http://richardhallgren.com/blog/?p=50">this post</a> ā¦). Say that we made a reference to a code library in one of our orchestrations. This code library is in version 1.0.0.0 when we build and deploy the orchestration to BizTalk and to the GAC. The setup in VS 2005 looks something like this.</p>
<p><a href="http://richardhallgren.com/blog/wp-content/uploads/2007/02/WindowsLiveWriter/BizTalkassemblyversionredirection_CA12/VersionReference3.jpg"><img src="http://richardhallgren.com/blog/wp-content/uploads/2007/02/WindowsLiveWriter/BizTalkassemblyversionredirection_CA12/VersionReference_thumb3.jpg" alt="" /></a></p>
<p>Then we make some minor changes in the code library, we fix them and set the version to 1.0.1.0. Build and deploy it. This means that we now have one 1.0.0.0 and one 1.0.1.0 version side-by-side in the GAC (as shown in the figure below).</p>
<p><a href="http://richardhallgren.com/blog/wp-content/uploads/2007/02/WindowsLiveWriter/BizTalkassemblyversionredirection_CA12/GAC8.jpg"><img src="http://richardhallgren.com/blog/wp-content/uploads/2007/02/WindowsLiveWriter/BizTalkassemblyversionredirection_CA12/GAC_thumb8.jpg" alt="" /></a></p>
<p>Coming from .NET the CLR should now load the 1.0.1.0 version as it identifies assemblies based on the assembly name, major or minor version (NOT the build and revision version), public key token and culture (<a href="http://www.informit.com/articles/article.asp?p=99977&seqNum=6&rl=1">more about this here</a>).</p>
<p>However, this does NOT work in BizTalk. BizTalk loads assemblies by fullname it has stored in the management database and the build and revision number are part of the fullname ā¦ This means we have to build and redelopy EVERY part where we like to use new version of the code library.</p>
<p>There is one way around this for emergency use. Say that one has a code library that is used in loads of BizTalk artifacts (A place where we store all base functionality for the solution). Rebuilding all those parts and redeploying it, just to be able to update the version number, is not going to happened! Itās to much work and to risky. **So itās possible to make a change in the <em>BTSBTSvc.exe.config</em> file instead. **In my case the change would be something like the below (<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/gngrfbindingredirect.asp">read more about here</a>).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; "><</span><span style="color: #000000; ">dependentAssembly</span><span style="color: #000000; ">></span><span style="color: #000000; ">
</span><span style="color: #000000; "><</span><span style="color: #000000; ">assemblyIdentity name</span><span style="color: #000000; ">=</span><span style="color: #000000; ">"</span><span style="color: #000000; ">StaticCodeLibrary</span><span style="color: #000000; ">"</span><span style="color: #000000; "> publicKeyToken</span><span style="color: #000000; ">=</span><span style="color: #000000; ">"</span><span style="color: #000000; ">32ab4ba45e0a69a1</span><span style="color: #000000; ">"</span><span style="color: #000000; "> culture</span><span style="color: #000000; ">=</span><span style="color: #000000; ">"</span><span style="color: #000000; ">neutral</span><span style="color: #000000; ">"</span><span style="color: #000000; "> </span><span style="color: #000000; ">/></span><span style="color: #000000; ">
</span><span style="color: #000000; "><</span><span style="color: #000000; ">bindingRedirect oldVersion</span><span style="color: #000000; ">=</span><span style="color: #000000; ">"</span><span style="color: #000000; ">1.0.0.0</span><span style="color: #000000; ">"</span><span style="color: #000000; "> newVersion</span><span style="color: #000000; ">=</span><span style="color: #000000; ">"</span><span style="color: #000000; ">1.0.1.0</span><span style="color: #000000; ">"</span><span style="color: #000000; ">/></span><span style="color: #000000; ">
</span><span style="color: #000000; "></</span><span style="color: #000000; ">dependentAssembly</span><span style="color: #000000; ">></span></div>
</code></pre></div></div>
Assembly loading policy from the GAC2007-01-17T17:27:04+00:00http://richardhallgren.com/assembly-loading-policy-from-the-gac<p>UPDATE: This does not apply to BizTalk ā¦ Iāve made an update <a href="http://richardhallgren.com/blog/?p=51">post here</a>. Sorry.</p>
<p>Weāre working with a lot of code libraries that we use in different parts of our BizTalk solutions. As the are used on several servers and by loads of different āBizTalk partsā (both in orchestrations and maps) itās important that we always keep the version number of the assemblies up to date. That means that every little change should increase the current version number. But as they are used in so many places people have started to skip this step as they thought they had to compile all parts that should use the new code (say itās a bug fix and youād like all āusing partsā of the assembly to load the updated version). This is where GAC loading policy comes to the resource!</p>
<p>First we have to understand that every .NET assembly is identified using four characteristics:</p>
<ul>
<li>Assembly name</li>
<li>Major or minor version</li>
<li>Public key token</li>
<li>Culture</li>
</ul>
<p>Then we need to know that the first version number in for example version 1.1.2.1 is the <strong>major version</strong>. The second is the <strong>minor version</strong> and the third and fourth are <strong>build, revision version number</strong>. So this means that if you have 1.1.2.1 installed and make a minor change the easiest way to use the new assembly is to change the one of the build or revision numbers (the third or fourth number). Then the CLR will load the new assembly without any other changes!</p>
<p>But sometimes we have to change the minor or major version - and we still donāt have to recompile a thing! We can use a publisher policy file. This is an example of such a file defined for version 1.0.0.0 moving to 2.0.0.0.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">configuration</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">runtime</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">assemblyBinding </span><span style="color: #FF0000; ">xmlns</span><span style="color: #0000FF; ">="urn:schemas-microsoft-com:asm.v1"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">dependentAssembly</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">assemblyIdentity </span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="BaseHelper"</span><span style="color: #FF0000; "> publicKeyToken</span><span style="color: #0000FF; ">="18517ea673f8584b"</span><span style="color: #FF0000; "> culture</span><span style="color: #0000FF; ">="neutral"</span><span style="color: #FF0000; "> </span><span style="color: #0000FF; ">/></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">bindingRedirect </span><span style="color: #FF0000; ">oldVersion</span><span style="color: #0000FF; ">="1.0.0.0"</span><span style="color: #FF0000; "> newVersion</span><span style="color: #0000FF; ">="2.0.0.0"</span><span style="color: #0000FF; ">/></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">dependentAssembly</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">assemblyBinding</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">runtime</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">configuration</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>This <a href="http://support.microsoft.com/kb/891030">kb article</a> describes what to do next:</p>
<ol>
<li><strong>Change the version and recompile.</strong> The first step is to create the new version of your component. After youāve done that, you will need to modify the version number in the AssemblyInfo file for your component. <br />
<strong>Create the publisher policy file. **Create the publisher policy file for the assembly using the format shown above. <br />
**Use Assembly Linker (Al.exe) to create the publisher policy assembly.</strong> The Assembly Linker is included with the .NET Framework SDK. To create the publisher policy assembly that redirects a binding from version 1.0 of Website.dll to version 2.0 using a publisher policy file called website.config, run the following command:</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; ">al /link:BaseHelper.config /out:policy.1.0.BaseHelper.dll /keyfile:c:\keyfile.snk</span></div>
</code></pre></div></div>
<p>This command will create a new assembly called policy.1.0.BaseHelper.dll. This naming convention is important, as indicated in the āWhat Is a Publisher Policy Assembly?ā section.</p>
<ol>
<li>
<p><strong>Install the publisher policy assembly into the Global Assembly Cache.</strong> The publisher policy assembly is installed into the GAC. It will be used by the .NET runtime when any application attempts to bind to version 1.0 of the BaseHelper.dll, and it will force the application to bind to the new version automatically.</p>
</li>
<li>
<p>**Install the new version into the Global Assembly Cache. **Install the new version of the component into the GAC. After the new version has been installed, the old version can be safely removed.</p>
</li>
</ol>
<p>So no more excuses for not updating the version number!</p>
Understanding persistence points2007-01-08T12:11:25+00:00http://richardhallgren.com/understanding-persistence-points<p>I found <a href="http://seroter.wordpress.com/2007/01/02/orchestration-handling-of-suspended-messages/">this post from Richard Seroterās blog</a> on persistence points interesting. The post deals with the basics in persistence points and how to tweak them to get a resumed orchestration to resume at an expected step. Not understanding persistence point and not thinking about them when planing and building an orchestration might cause some strange bugs and errors.</p>
Testable data access code2007-01-03T15:26:55+00:00http://richardhallgren.com/testable-data-access-code<p>As one of the most important rules for a test <strong>is that it canāt rely on state</strong>, Iāve always found automated data access testing hard. As I view it there are three approaches to accomplish reliable testing of such a layer:</p>
<ol>
<li>A local database that is restored for each and every test.</li>
<li>Using transactions that can rollback the database after the test completed</li>
<li>Using mock objects</li>
</ol>
<p>I guess all of them has drawbacks and are suitable in different situations.</p>
<p>It would be possible to have ones data access layer connected to a local database thatās fully restored to a know state for every test. But as the database grows that process would soon get extremely slow. And as one of the requirements for testing and test driven development is that is possible to test often (and if we like to test often is has to be fast) I think this is a method that only works when we have a simple tiny database (something we almost never have ā¦).</p>
<p>Another way of do it would be use transactions to rollback each test operation on the database. A problem here is that we might use transactions within the access layer we like to test! We might even have transactions disabled. This <a href="http://msdn.microsoft.com/msdnmag/issues/05/06/UnitTesting/default.aspx">excellent article</a> by Roy Osherove discusses the possibilities of using the transactions from Enterprise Services (COM+) for rolling back database operations. This is an interesting approach and with the new <a href="http://msdn2.microsoft.com/en-us/library/system.transactions.aspx">System.Transactions namespace in .NET 2.0</a> things should be even easier. But still, if one is using transactions in the actually access layer that is being tested we still have to use something else. Another problem is that transactions always will cause a minor performance hit that might grow when using it in a large project with loads of tests.</p>
<p>And then we have mock objects. The first thing we have to think about here is what we should test in a unit test? Should we really test the all the way to the database or should we stay within the boundaries of the application? My option is that a unit test should not test all the way through to the database, then itās a integration test. <strong>However</strong> it might be very useful to have such a test in our test suite. If we decide to actually test trough to the database mock object will not do us any good. They will only be able to test that the right method in the data access class were called in correct order.</p>
<p>Some links I found useful:<br />
<a href="http://weblogs.asp.net/rosherove/archive/2004/12/10/279258.aspx">http://weblogs.asp.net/rosherove/archive/2004/12/10/279258.aspx</a><br />
<a href="http://weblogs.asp.net/rosherove/articles/dbunittesting.aspx">http://weblogs.asp.net/rosherove/articles/dbunittesting.aspx</a><br />
<a href="http://weblogs.asp.net/rosherove/archive/2004/07/20/187863.aspx">http://weblogs.asp.net/rosherove/archive/2004/07/20/187863.aspx</a><br />
<a href="http://msdn.microsoft.com/msdnmag/issues/04/10/NMock/default.aspx">http://msdn.microsoft.com/msdnmag/issues/04/10/NMock/default.aspx</a><br />
<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/aspnet-testwithnunit.asp">http://msdn.microsoft.com/libraryā¦testwithnunit.asp</a><br />
<a href="http://msdn.microsoft.com/msdnmag/issues/05/06/UnitTesting/default.aspx">http://msdn.microsoft.com/msdnmagā¦default.aspx</a></p>
Web service times out before the orchestration completes2006-12-20T10:09:33+00:00http://richardhallgren.com/web-service-times-out-before-the-orchestration-completes<p>Today we ran into some problems when making a call to a web service that took more than 90 seconds via the SOAP adapter. After 90 seconds we got a āSystem.Net.WebException: The operation has timed-outā error in return. It turned out that we had to set the <em>SOAP.ClientConnectionTimeOut</em> context property for the request message. We did this in the message construction using the following code.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; ">MyRequestMessage(SOAP.ClientConnectionTimeout) = 200000;</span></div>
</code></pre></div></div>
<p>I found this <a href="http://www.winterdom.com/weblog/2005/07/17/WebServiceCallTimeoutInBizTalk.aspx">post by Thomas Restrepo</a> useful for understanding both the problem and solution. Apparently the default value is 90000 (90 seconds) before the adapter times out. This <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/BTS_2004WP/html/5cab05ab-6848-4f6c-8d11-9abc4dd1d1fa.asp">article on MSDN</a> is also an excellent read when working with web services and BizTalk server.</p>
How to set a custom file name using the file adapter in BizTalk2006-12-15T10:28:26+00:00http://richardhallgren.com/how-to-set-a-custom-file-name-using-the-file-adapter-in-biztalk<p>Found this <a href="http://www.codeproject.com/useritems/SendHandlerMacro.asp">article</a> on the code project on how to set a custom name on a output file - something I recently had to do. It also contains a list of all the macros that are available in the file adapter - so does this <a href="http://blogs.msdn.com/oallen/archive/2004/03/19/92673.aspx">post from Owen Allen</a>.</p>
Advanced Microsoft BizTalk Server 2004 and Microsoft Operations Manager 2005 Scenarios2006-12-15T07:27:02+00:00http://richardhallgren.com/advanced-microsoft-biztalk-server-2004-and-microsoft-operations-manager-2005-scenarios<p>Scott Colestock has a vary thorough <a href="http://www.microsoft.com/technet/prodtechnol/biztalk/biztalk2004/maintain/advanced-biztalk-mom.mspx">article</a> on <a href="http://technet.microsoft.com/en-us/default.aspx">TechNet</a> about <a href="http://www.microsoft.com/mom/default.mspx">MOM 2005</a> and BizTalk. Itās really amazing what it possible to accomplish when one gets these two solutions to play together.</p>
BOM - Byte Order Mark in BizTalk output2006-12-13T15:38:05+00:00http://richardhallgren.com/bom-byte-order-mark-in-biztalk-output<p>Today was another day of new BizTalk problems ā¦ The task was easy; produce a XML file and send to a receiving system. Fine. Done. ā¦ Not.</p>
<p>The receiving system could not read the file because of some strange characters in the beginning of the file! It looked something like the below when opening the file in a fancy text editor (<a href="http://www.ultraedit.com/">UltraEdit</a> or <a href="http://www.textpad.com/">TextPad</a> for example).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; ">iĀ»Āæ</span><span style="color: #0000FF; "><?</span><span style="color: #FF00FF; ">xml version="1.0" encoding="utf-8"</span><span style="color: #0000FF; ">?></span></div>
</code></pre></div></div>
<p>After a couple of very interesting (:/) hours of <a href="http://en.wikipedia.org/wiki/Google_(verb)">Googling</a> I found this from Ben McFarlin</p>
<blockquote>
>
> It is because internal BizTalk messages are in UTF8 format and include
the byte order mark. When you added the xml declaration for UTF16 it
confused the engine; the declaration read UTF16 but the byte order mark indicated UTF8.
>
> </blockquote>
<p><a href="http://richardhallgren.com/blog/wp-content/uploads/2006/12/WindowsLiveWriter/BOMByteOrderMark_EA75/preserveBOM%5B5%5D5.jpg"><img src="http://richardhallgren.com/blog/wp-content/uploads/2006/12/WindowsLiveWriter/BOMByteOrderMark_EA75/preserveBOM_thumb%5B5%5D5.jpg" alt="Preserve BOM" /></a>When I finally found the cause the solution was easy. Just another of those <a href="http://support.microsoft.com/kb/921044">weird properties</a> ā¦ This time itās called <em>Preserve BOM</em> (on the properties of the XML Assembly pipeline component - see figure on the right). <em>BOM</em> of course stands for <em>Byte Order Mark</em>.</p>
Gmail and Opera Mini on the phone!2006-12-13T11:51:46+00:00http://richardhallgren.com/gmail-and-opera-mini-on-the-phone<p>A couple of months ago I found the new Gmail mobile application. Itās a clean small Java application that one downloads to the mobile phone for accessing the Gmail account.</p>
<p>The application has easy access to almost all of the features that the ordinary web interface has. There was (and probably still are) an mobile version of the web interface but it didnāt have the easy access to all the different menus as this application has. I really like it and use it several times each day.</p>
<p>The supported devices are listed <a href="http://mail.google.com/support/bin/answer.py?answer=50425">here</a> and to get on your phone all you do is to visit this URL <a href="http://gmail.com/app">http://gmail.com/app</a> with your device.</p>
<p>Another cool little application is the <a href="http://www.operamini.com/">Opera Mini browser</a>. These a full feature list <a href="http://www.operamini.com/features/">here</a>. Basically it transforms the pages so that they fit the mobile screen, and itās fast! It also has some special features for navigation on small screens. And it supports RSS bookmarks!</p>
Nevermind the XML namespaces in Xpath expressions2006-12-11T15:45:59+00:00http://richardhallgren.com/nevermind-the-xml-namespaces-in-xpath-expressions<p>Understanding <a href="http://www.w3.org/TR/xpath">Xpath</a> expressions is definitely a success factor when working with BizTalk development. Xpath is extremely powerful (when one gets it right) but itās one of the must frustration techniques Iāve ever worked with! Xpath is one of those languages that either gives you to answer you want to a query - or (more often) just doesnāt give you anything in return! In 99 percent of the cases this means that you missed something in your match. In 99 percent of these cases this means that you got some problems with namespaces in the XML document your querying (This is certainly true when working with BizTalk that ānamespace-heavyā). One technique to get around this is to use the same approach as BizTalk itself uses - the <a href="http://www.w3.org/TR/xpath#function-local-name">Xpath local-name() function</a>!</p>
<p>Consider the following XML document.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><</span><span style="color: #800000; ">Message </span><span style="color: #FF0000; ">xmlns:ns0</span><span style="color: #0000FF; ">="Standard.Envelope/1.1"</span><span style="color: #FF0000; "> xmlns:xsi</span><span style="color: #0000FF; ">="http://www.w3.org/2001/XMLSchema-instance"</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">ns0:Envelope</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Header</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">MessageTypeInfo</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">MessageType</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">.</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">MessageType</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">MessageTypeInfo</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Action</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">INSERTED</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Action</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">Addressees</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "><</span><span style="color: #800000; ">SenderCode</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">Mill</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">SenderCode</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Addressees</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Header</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">ns0:Envelope</span><span style="color: #0000FF; ">></span><span style="color: #000000; ">
</span><span style="color: #0000FF; "></</span><span style="color: #800000; ">Message</span><span style="color: #0000FF; ">></span></div>
</code></pre></div></div>
<p>The Xpath expression below will hit the <em>Envelope _node. But isās very fragile! As soon as the namespace prefix changes (It might change to _ns1</em> and namespace <em>ns0</em> will be used for something else.) youāll end up with an empty result.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; ">/Message/ns0:Envelope</span></div>
</code></pre></div></div>
<p>However, if one uses the below expressions instead - that makes use of the local-name function - it ignores the namespace and only cares about the name of the node (<em>Envelope</em> that is ;)). And this is of course far less sensitive to change.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; ">/Message/*[local-name()='Envelope']</span></div>
</code></pre></div></div>
BizTalk Deploy Tool2006-12-11T14:44:13+00:00http://richardhallgren.com/biztalk-deploy-tool<p>Iām currently working in a stabilization phase on a deployment application for BizTalk 2006 projects. We based the solution on the <a href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=b4d6499f-0020-4771-a305-c156498db75e">Enterprise Solutions Build Framework</a> and the <a href="http://msdn2.microsoft.com/en-US/library/aa559050.aspx">BizTalk Explorer Object Model</a>. Basically our solution has a GUI that makes it possible to point out which artifacts one likes to deploy (from the developers local BizTalk server).</p>
<p>The application then figures out all the dependencies that the selected artifacts has (In our solution an Orchestration for example might have > 20 dependencies to different schemas, pipelines, C# libraries etc, etc).</p>
<p>All DLL:s of the different artifacts are then extracted from the local GAC (where they exist when deployed to the local BizTalk). These DLL:s are then packed in to one single deployment package also containing a single XML file that keeps track of the dependencies and the order of witch they have to be deployed in BizTalk (the most depending schemas first and so on). The XML file also contains other meta data information such as ports the artifacts use etc.</p>
<p>This package is then loaded into another part of the application were itās possible to point out the different servers one like to deploy to. This view then shows information about what has to be done on the server to make it possible to deploy without conflicts (One might have running Orchestration or suspended messages for example that has to be stopped or terminated.). At this stage we also check the naming of the different artifacts. These have to comply with the naming conventions that are configured in the config file of the applications (a warning is shown if the artifact doesnāt validate towards these).</p>
<p>When no warnings (its possible to override a warning) or conflicts are shown one can deploy. We then move the deploy scripts to the servers and use the <a href="http://msdn2.microsoft.com/en-us/library/wea2sca5.aspx">MSBuild</a> tasks in the <a href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=b4d6499f-0020-4771-a305-c156498db75e">SBF</a> to deploy everything for us. We really saved some serious time with this approach and even if it took us a while to get everything working itās been well worth it!</p>
<p>We have a huge feature list for the next phase of the tool and are planing to and support for <a href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=85ef830b-5903-4872-8071-4d4123a5553b">BizUnit</a> tests in the DLL:s (so that one gets a warning when deploying a Orchestration without etc). We also like to add more meta data about the port and make it possible to configure new ports as a part of the deployment process. Etc, etc ā¦</p>
<p>Feel free to comment or write we line for further information about this approach. It would also be interesting to hear about other approaches for deployment and what kind of features these solutions have.</p>
ARCast - Patterns and Anti-Patterns for SOA2006-12-11T13:37:10+00:00http://richardhallgren.com/arcast-patterns-and-anti-patterns-for-soa<p>Iām a loyal <a href="http://channel9.msdn.com/shows/ARCast_with_Ron_Jacobs">ARcast</a> listener and I think Iāve listened to most of the shows that ever been produced (at least those that are available in the archive). I also listen to a couple of other podcasts that are focusing on .NET and Microsoft techniques (for example <a href="http://www.dotnetrocks.com/">.NET Rocks!</a>) and in my opinion ARcast is by far the most rewarding (I guess this is both a matter of taste and depending on what kind of work one does.)! However these two shows on <em>Patterns and anti-patterns for SOA</em> (<a href="http://channel9.msdn.com/ShowPost.aspx?PostID=259342">part 1</a> and <a href="http://channel9.msdn.com/ShowPost.aspx?PostID=260161">part 2</a>) really stands out!</p>
<p>They really got me thinking of a couple of anti-patterns the project Iām currently working on are stuck in. And Ron Jacob delivers (as always) the message with a lot of humor and enthusiasm. Recommended!</p>
XML comment in BizTalk output message2006-12-11T13:18:36+00:00http://richardhallgren.com/xml-comment-in-biztalk-output-message<p>We ran into an issue today when we had to have an XML comment just below the XML declaration in a message weāre producing in our BizTalk 2006 solution. We needed to produce something like the below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #0000FF; "><?</span><span style="color: #FF00FF; ">xml version="1.0"</span><span style="color: #0000FF; ">?></span><span style="color: #000000; ">
</span><span style="color: #008000; "><!--</span><span style="color: #008000; "> Comment goes here </span><span style="color: #008000; ">--></span></div>
</code></pre></div></div>
<p>Our first approach was to create a map in the send port and to have a custom XSLT template in there that added the comment before the whole transformation process started. We actually got this to work but it meant that we had to have a whole new map with a separate XSLT document in the project!</p>
<p><a href="http://richardhallgren.com/blog/wp-content/uploads/2006/12/WindowsLiveWriter/XMLcommentinBizTalkoutputmessage_C9D4/xml%20assembler%20settings%5B1%5D5.jpg"><img src="http://richardhallgren.com/blog/wp-content/uploads/2006/12/WindowsLiveWriter/XMLcommentinBizTalkoutputmessage_C9D4/xml%20assembler%20settings_thumb%5B1%5D5.jpg" alt="" /></a>Eventually we found a property called <em>Xml Asm Processing Instructions</em> (highlighted in the figure - click it to view it in original size) on the XML assembly component (used in the standard XMLTransmit pipeline).</p>
<p>We just put the comment as a value in this property and we were done! No new artifacts or code! Just a weird property - typical BizTalk behavior!</p>
Virtual Desktop Manager in XP PowerToys2006-09-29T08:57:21+00:00http://richardhallgren.com/virtual-desktop-manager-in-xp-powertoys<p>Today someone complained about Windows XPās lack of virtual desktops and that Mac had the possibility to have several desktops active with different content. I remembered that had tried something like that a couple of years ago and after a while I found <a href="http://www.microsoft.com/windowsxp/downloads/powertoys/xppowertoys.mspx">Microsoft PowerToys for Windows XP</a> again.</p>
<p>The PowerToys package contains several small XP add-ins. For example the <em><strong>Virtual Desktop Manager</strong></em>!</p>
<p><a href="http://richardhallgren.com/blog/wp-content/uploads/2006/09/WindowsLiveWriter/VirtualDesktopManagerinXPPowerToys_9965/desktops%5B1%5D.jpg"><img src="http://richardhallgren.com/blog/wp-content/uploads/2006/09/WindowsLiveWriter/VirtualDesktopManagerinXPPowerToys_9965/desktops.jpg" alt="" /></a></p>
<p>As the image above show the manager makes it possible to have four separate desktops running at one - nice! A few configurations tips that I found useful was <strong><em>turn of the shared desktops option</em></strong> and to <em><strong>set the shortcut</strong></em> for showing the desktops to <em>alt-Ā§</em> (thatās close to the <em>alt-tab</em> option).</p>
<p><a href="http://richardhallgren.com/blog/wp-content/uploads/2006/09/WindowsLiveWriter/VirtualDesktopManagerinXPPowerToys_9965/multitask%5B1%5D.jpg"><img src="http://richardhallgren.com/blog/wp-content/uploads/2006/09/WindowsLiveWriter/VirtualDesktopManagerinXPPowerToys_9965/multitask.jpg" alt="" /></a></p>
<p>An other cool application in the PowerToys package is the <em><strong>Alt-Tab Replacement</strong></em> that shows a small preview of the different windows one is multi tasking between (as shown in the image above).</p>
Visual Studio Database Project2006-09-28T09:00:54+00:00http://richardhallgren.com/visual-studio-database-project<p>Iāve realized that I never understood the full potential of the Visual Studio Database Project. None of the projects Iāve worked on has had a effective process on handling changes and versioning of the database schema. Test data, build scripts, changes to the local development database versus the test and production base has also been a bit bumpy. Iāve havenāt understood that working with the Database Project potentially could solves a lot of these challenges .</p>
<p>A <a href="http://www.awprofessional.com/articles/article.asp?p=31764&seqNum=1&rl=1">chapter</a> from the <a href="http://www.awprofessional.com/bookstore/product.asp?isbn=0672323435&rl=1">Database Access with Visual BasicĀ® .NET</a> book describes some features in the Database Project.</p>
CSS Control Adapter Toolkit2006-09-28T06:40:09+00:00http://richardhallgren.com/css-control-adapter-toolkit<p>A while ago Microsoft released the <a href="http://weblogs.asp.net/scottgu/archive/2006/05/02/CSS-Control-Adapter-Toolkit-for-ASP.NET-2.0-.aspx">CSS Control Adapter Toolkit</a> for ASP.NET 2.0. It finally makes it possible to use all the time saving ASP.NET controls in 2.0 without all the horrible HTML they used to produce. The toolkit gives access to the now improved source of the following adapter controls:</p>
<ul>
<li>Menu</li>
<li>TreeView</li>
<li>GridView</li>
<li>DetailsView</li>
<li>FormsView</li>
<li>DataList</li>
<li>Login</li>
<li>ChangePassword</li>
<li>CreateUser</li>
<li>PasswordRecovery</li>
<li>LoginStatus</li>
</ul>
<p>Make sure to have the latest <a href="http://weblogs.asp.net/scottgu/archive/2006/09/08/CSS-Control-Adapter-Toolkit-Update.aspx">update</a>. The update fixed a few things in the old controls and added a couple more.</p>
<p>One can almost think of the this toolkit as a patch for ASP.NET and <strong>when creating a public website this really is a must</strong>!</p>
BizTalk Server 2006 Troubleshooters Guide2006-09-27T20:16:10+00:00http://richardhallgren.com/biztalk-server-2006-troubleshooters-guide<p>Iāve just started reading the new <a href="http://blogs.msdn.com/biztalk_server_team_blog/archive/2006/09/13/752294.aspx">BizTalk Server 2006 Troubleshooters Guide</a>, itās basically 133 pages packed with best practices and common pitfalls to avoid. Itās seems to be a great resource and Iāll try to use this blog to summarize some of the different parts - just have to get some more time! ;)</p>
FileSystemWatcher Class2006-09-25T10:02:04+00:00http://richardhallgren.com/filesystemwatcher-class<p>I just found the <a href="http://msdn2.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx">FileSystemWatcher class</a> in the <a href="http://msdn2.microsoft.com/en-us/library/29kt2zfk.aspx">System.IO</a> namespace. It provides the functionality to listen on the file system for changes on a file or directory. The class fires a couple of events: <em>Changed</em>, <em>Created</em>, <em>Deleted</em> and <em>Renamed</em>.</p>
<p>I didnāt know of this class until now. I always thought one had to write a service to accomplish something like this! Definitely very useful!</p>
More BizTalk and integration related Webcasts!2006-09-20T18:40:59+00:00http://richardhallgren.com/more-biztalk-and-integration-related-webcasts<p>I found a couple of really good webcasts <a href="http://www.microsoft.com/events/series/msdnbpi.mspx">here</a>!</p>
VS 2005 project on the old IIS2006-09-13T06:24:29+00:00http://richardhallgren.com/vs-2005-project-on-the-old-iis<p>As most people know the web project that are created and tested in VS 2005 run on an internal web server (called Cassini).</p>
<p>In some situations this is useful as it enables one to quickly get the project up and running and start testing. But as the sites usually are going to run on an IIS in production I usually like to test it and develop it on one as well (for other reasons, check <a href="http://codebetter.com/blogs/peter.van.ooijen/archive/2006/09/12/Switching-from-the-VS-development-server-to-IIS.aspx">this</a> out).</p>
<p>Hereās <a href="http://codebetter.com/blogs/peter.van.ooijen/archive/2006/09/12/Switching-from-the-VS-development-server-to-IIS.aspx">a good article</a> on how to change the setting that makes VS behave as it it used to (put it on an URL and create a virtual directory for it).</p>
<p>The only drawback I can think of is that it becomes a bit more complicated when it comes to deleting a project ā¦</p>
Excel into BizTalk 2006 - the easy way2006-09-11T20:08:41+00:00http://richardhallgren.com/excel-into-biztalk-2006-the-easy-way<p>FarPoint just released a <a href="http://www.fpoint.com/biztalk/default.aspx">pipeline disassembler component for Excel documents</a> (called āFarPoint Spread for MicrosoftĀ® BizTalkĀ® Server 2006ā). It looks pretty cool! It comes with a āSpreadsheet Schema wizardā that integrates with Visual Studio 2005. It could potentially save a lot of work.</p>
<p>I guess the reason that Microsoft hasnāt released anything like this is that they like to push the use of Infopath. Basically everything would be much easier if one uses Infopath, but there might be situations where this isnāt possible.</p>
Viewstate2006-09-11T07:10:45+00:00http://richardhallgren.com/viewstate<p>Before writing a new user or custom control read <a href="http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx">this article</a> about Viewstate!</p>
BizTalk Webcasts2006-09-09T10:58:53+00:00http://richardhallgren.com/biztalk-webcasts<p>Iām not sure of how many know of <a href="http://msdn.microsoft.com/biztalk/community/webcasts/default.aspx">these Webcasts</a> that Microsoft keep publishing. I didnāt know of them until recently and that Iāve learnt a lot by viewing them. I find it a excellent way of learning new things and tips from some of the most skilled people working with BizTalk.</p>
<p>I recommend the following:</p>
<ul>
<li><a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?EventID=1032284450&EventCategory=5&culture=en-us&CountryCode=US">Design Human Workflow Solutions with BizTalk Server 2004</a> (medium)<br />
This is a <strong>absolute must to watch</strong>. The demo is this presentation is a killer! Itās a complete workflow system build in **four **days that really shows the strengths of BizTalk. Itās also emphasizes some important architecture best practices in BizTalk.</li>
<li><a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?EventID=1032278710&EventCategory=5&culture=en-us&CountryCode=US">BizTalk Web Services and WSE</a> (medium)</li>
<li><a href="http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032247084&Culture=en-US">Getting up to speed with BizTalk Server 2004 for the Visual Studio .NET Developer</a> (basic)</li>
<li><a href="http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032262823&EventCategory=3&culture=en-US&CountryCode=US">Biztalk Server 2004 Architecture</a>** (basic)</li>
<li><a href="http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032262826&Culture=en-US">Biztalk Server 2004 Orchestration for the Visual Studio .NET Developer</a> (basic)</li>
</ul>
BizTalk exams passed!2006-09-09T10:44:33+00:00http://richardhallgren.com/biztalk-exams-passed<p>Yesterday I passed both the 2004 exam (<a href="http://www.microsoft.com/learning/exams/74-135.asp">074-135: Developing E-Business Solutions Using Microsoft BizTalk Server 2004</a>) and the new 2006 BizTalk exam (070-235: TS: <a href="http://www.microsoft.com/learning/exams/70-235.asp">Developing Business Process and Integration Solutions by Using MicrosoftĀ® BizTalkĀ® Server 2006</a>)!</p>
<h3 id="webcasts">Webcasts</h3>
<p>When I first started studying for the exam I hadnāt really worked with BizTalk. These Webcasts provided an easy introduction to the basics of the products:</p>
<ol>
<li><a href="http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032247084&Culture=en-US">Getting up to speed with BizTalk Server for .NET Developer</a></li>
<li><a href="http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032262826&Culture=en-US">BizTalk Orchestration</a></li>
<li><a href="http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032262823&EventCategory=3&culture=en-US&CountryCode=US">Biztalk Server 2004 Architecture</a></li>
</ol>
<p>The Webcasts are help by <a href="http://blogs.msdn.com/scottwoo/">Scott Woodgate</a>. He used to be the product manager for BizTalk and knows it inside out (besides being a skilled presenter).</p>
<h3 id="installation">Installation</h3>
<p>Next thing I did was to install a Virtual PC with a Windows 2003 server. Then I used <a href="http://blogs.msdn.com/luke/articles/211384.aspx">this list</a>. The list saved me from some major pitfalls while installing BizTalk (especially 2004 is known to be a messy installation)!</p>
<p>The only problem I ran into during the installation was a collation error on the SQL server (BizTalk Server does not support case-sensitive collations, use <em>Latin1_General_CI_AS</em>).</p>
<h3 id="tutorials">Tutorials</h3>
<p>Then I worked my way through <a href="http://www.microsoft.com/downloads/details.aspx?familyid=9C64562C-3FA7-49BA-885E-82213D00776E&displaylang=en">these tutorials</a>. They cover a big part of the product. I can also recommend reading the <a href="http://book.itzero.com/read/microsoft/0505/Sams.Microsoft.BizTalk.Server.2004.Unleashed.Nov.2004.eBook-LiB_html/">BizTalk Unleashed 2004</a> book. Make sure to understand everything in the tutorials as most of it actually will show up on the exam. Make sure to pay extra attention to deployment and the development of business rules! Of course one also has to understand the basics of Orchestration and XML mapping.</p>
<h3 id="exams">Exams</h3>
<p>To pass the exams youāll have to <strong>understand the whole architecture</strong> and when messages are written to the message database (<em>dehydrate</em> and <em>hydrate</em>). <strong>Understand pipelines</strong> - develop your own pipeline and deploy it to really understand this part (remember all the interfaces etc). While developing pipeline use the different <strong>pipeline testing tools</strong> that are available (pipeline.exe etc). Read about <strong>message patters</strong> and particularly the <em>convoy pattern</em> etc. You will need to know most of the <strong>mapping functiods</strong> and what they are used for. Use and understand the <em>import</em>, <em>include</em> and <em>redefine</em> <strong>functionality in the schema editor</strong>.</p>
<p>One big miss I did while studying was the security part and what <strong>different BizTalk users groups that exists</strong>. Use <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bts06coredocs/html/a01603bd-4105-4691-819d-de43b00b40f3.asp">this list</a> and learn the most important ones (both the Windows and the SQL Server Roles). To pass the exam you donāt really have to know that much about the specifics of <em>BAS</em>, <em>BAM</em> ands <em>HWS</em> - you do need to know what the different solutions are used for and what their limits are.</p>
<p>The new exams are a bit different as they involve setting up a lot of action-lists where one drag and drop actions to create a list of actions for completing a described task. No information about how many actions are required in the finished list etc. However the 2006 is āeasierā as it deals a lot with actual development tasks and not so much with security things and details as the old ones (like specific user groups and interfaces etc).</p>
<p>A few tips if your planing to take the 2006 exams is that you study the new <strong>BTSTask tool</strong>, developing business rules using the <strong>Business Rule Composer</strong> tool and BAM (Business Activity Monitoring) and especially <strong>the process of configuring BAM</strong>.</p>
Resources ā¦2006-08-31T05:59:16+00:00http://richardhallgren.com/resources<p>Iāve started reading <a href="http://www.hanselman.com/blog/ScottHanselmans2006UltimateDeveloperAndPowerUsersToolListForWindows.aspx">this list</a>. Jisses! Thereās is literally a ton of links to excellent resources here!</p>
<p><strong>Validation</strong></p>
<p>Iāll work my way down the list when I have some more time. However I found <a href="http://www.peterblum.com/VAM/Home.aspx">this</a>, seems like it could have saved my a lot if Iād known about earlier. Itās a package with validation controls for ASP.NET for every situation. Looks really good.</p>
<p><strong>Date</strong></p>
<p><a href="http://www.peterblum.com/DateControls/Home.aspx">This</a> seems like another usefull resource. Loads and loads of different date controls. Iāll have to remeber this site the next time Iāll nedd one.</p>
My first NNUG meeting2006-08-30T05:32:30+00:00http://richardhallgren.com/my-first-nnug-meeting<p>I just came back from my first <a href="http://www.nnug.no/">NNUG meeting</a> (.NET user group) ever! The meeting consisted of two presentations (plus some Microsoft info about <a href="http://www.microsoft.com/events/teched2006/">Tech Ed</a> etc), one about the new <a href="http://wf.netfx3.com/">Windows Workflow Foundation</a> and one about the <a href="http://msdn.microsoft.com/asp.net/downloads/providers/default.aspx?pull=/library/en-us/dnaspnet/html/asp02182004.asp">Provider model in .NET 2.0</a>.</p>
<p>Neither of them were really breathtaking. Besides the fact that deleting the namespace in the web.coning in ASP.NET 2.0 actually enables the XML config code hinting!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; "><</span><span style="color: #000000; ">configuration
xmlns</span><span style="color: #000000; ">=</span><span style="color: #000000; ">"</span><span style="color: #000000; ">http://schemas.microsoft.com/.NetConfiguration/v2.0</span><span style="color: #000000; ">"</span><span style="color: #000000; ">></span></div>
</code></pre></div></div>
<p>Becomes</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div><span style="color: #000000; "><</span><span style="color: #000000; ">configuration</span><span style="color: #000000; ">></span></div>
</code></pre></div></div>
<p>Apparently itās a bug in Visual Studio 2005! Itās always irritated me as Iāve seen it working in different presentations etc. At leats itās an easy fix.</p>
<p>The new <a href="http://wf.netfx3.com/">Windows Workflow Foundation</a> is basically Orchestration from Biztalk that Microsoft put into a isolated component. This makes it possible to call orchestrations like processes (called workflows) from all .NET code.</p>
<p>I also got to talk to a guy with heavy <a href="http://www.microsoft.com/biztalk/">Biztalk 2004</a> experience. Itās interesting as my new job will involve some major Biztalk development. Apparently Biztalk has some issues consering the XML mapper and the XSLT it generates (Iāve heard that before). Sounds like I got some XSLT writing a head of me ā¦</p>
The Regulator!2006-08-29T14:26:30+00:00http://richardhallgren.com/the-regulator<p>I had to write a few regular expression for a project today. As always I couldnāt remember the syntax. After a bit of searching I found this <a href="http://tools.osherove.com/Default.aspx?tabid=185">excellent free tool</a>!</p>
<p>It saved me a lot of time. It even generates .NET code.</p>
Code formater Plugin for Windows Live Writer2006-08-26T13:11:57+00:00http://richardhallgren.com/code-formater-plugin-for-windows-live-writer<p>I use <a href="http://windowslivewriter.spaces.live.com/">Windows Live Writer</a> for writing and posting to my blog. However Iāve always had problems with code formating. Until now!</p>
<p><a href="http://http://www.codeplex.com/Wiki/View.aspx?ProjectName=WlwCodeFormatter">This little plug in</a> to Live Writer does the job!</p>
<p>Thanks to Steve Dunn whos excellt blog youāll find <a href="http://stevedunns.blogspot.com/">here</a></p>