Host Integration Server 2006 – Service Pack 1: Now Available

Wow, it must be the week for Service Pack announcements. First we see the BizTalk 2006-R1 SP and now HIS 2006 gets its very own SP.  Details from about the release are below. Please note, that the Knowledge Base articles listed below might not be active for a couple of days. So if you try and them and they don’t work, give it a day before you hammer me on posting dead links.

>>>>

Host Integration Server 2006 Service Pack 1 is now available for download at the following location:

http://www.microsoft.com/downloads/details.aspx?FamilyID=c0cc5e8d-fc47-41ac-bcad-67832249eb41

Host Integration Server 2006 Service Pack 1 provides the latest updates for Microsoft Host Integration Server 2006 and Microsoft BizTalk Adapters for Host Systems. It delivers customer requested hotfixes that improve the quality, reliability and supportability of Host Integration Server 2006 and BizTalk Adapters for Host Systems. The following two Knowledge Base articles will be available soon to describe the list of fixes and how to download the service pack:

KB 979238 – A list of the bugs that are fixed in Host Integration Server 2006 Service Pack 1 – http://support.microsoft.com/kb/979238

KB 979497 – How to obtain the latest Host Integration Server 2006 service pack – http://support.microsoft.com/kb/979497

Congratulations to the HIS Product Team, BPD Engineering Services team and CSS engineers who made this happen.  Having this service pack available for our customers now allows us to efficiently support customers and focus on future releases of Host Integration Server.

>>>>

Cheers and keep on BizTalking

Peter

ESB Itinerary Selector: Parameter name cannot be null or an empty string. Parameter name: key

Event Type:Error

Event Source:BizTalk ESB Toolkit 2.0

Event Category:None

Event ID:6060

Date:1/31/2010

Time:7:06:00 AM

User:N/A

Computer:WS03_OFFICE07

Description:

Parameter name cannot be null or an empty string.

Parameter name: key

Source: Microsoft.Practices.ESB.Resolver.ResolverMgr

Method: System.Collections.Generic.Dictionary`2[System.String,System.String] Resolve(Microsoft.Practices.ESB.Resolver.ResolverInfo, Microsoft.BizTalk.Message.Interop.IBaseMessage, Microsoft.BizTalk.Component.Interop.IPipelineContext)

Error Source: Microsoft.Practices.EnterpriseLibrary.Caching

Error TargetSite: Void ValidateKey(System.String)

Error StackTrace: at Microsoft.Practices.EnterpriseLibrary.Caching.Cache.ValidateKey(String key)

at Microsoft.Practices.EnterpriseLibrary.Caching.Cache.GetData(String key)

at Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager.GetData(String key)

at Microsoft.Practices.ESB.Cache.Cache`1.Get(String key, Boolean returnAndRemove)

at Microsoft.Practices.ESB.Cache.Cache`1.Get(String key)

at Microsoft.Practices.ESB.Resolver.ResolverMgr.GetResolver(ResolverInfo info)

at Microsoft.Practices.ESB.Resolver.ResolverMgr.Resolve(ResolverInfo info, IBaseMessage message, IPipelineContext pipelineContext)

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

The issue was that I had the BRI string like this: BRI:// instead of BRI:\\ in the pipeline component’s configuration. The latter is the correct way

How the Parallel Actions shape works

How the Parallel Actions shape works

Hi all

Lots of people think, that if they use a Parallel Actions shape, they get things done
in parallel. Well, rethink that. An orchestration executes in just one thread, so
no chance of getting anything to run in parallel. At runtime, the shapes in the parallel
shape are simply serialized.

But what is the algorithm, then?

Well, I did some tests. First of all, I created this simple orchestration:

image

It’s a receive shape to fire up the orchestration and then a parallel shape with four
branches and five expression shapes in each. The code in each expression shape is
this:

 1: System.Diagnostics.Trace.WriteLine("X.
Y");

where X is a number indicating the branch and Y is a sequence number within the branch.
This means that X=2 and Y=3 is the third expression shape in the second branch and
X=4 and Y=1 is the first expression shape in the fourth branch.

Running this orchestration I get this result from DebugView:

image

So as you can see, the entire first branch is executed, then the entire second branch,
and so on until the fourth branch has finished. Sounds easy enough. But lets try some
other scenarios like this one:

image

In essence I have thrown in a receive shape in branch 2 to see if branches three and
four will still have to wait until branch 2 has finished.

The result can be seen here:

image

So as you can see, the second branch stops after the second shape because now it awaits
the receive shape. Branches three and four are then executed and after I send in a
message for the receive shape, the second branch completes.

So some form of parallelism is actually achieved, but only when a shape takes too
long to handle. Lets see what happens with a Delay shape instead like this:

image

I have switched the Receive Shape for a Delay shape, and I have set the Delay shape
to wait for 100 milliseconds. The result of this is the same as with the Receive shape:

image

Then I tried setting the Delay shape to just 1 millisecond, but this gave the same
result.

With shapes that take time in two branches, like this:

image

And the Delay is still set at one millisecond. I get the following result:

image

So as you can see, the Receive shape causes branch 2 to stop executing, and the Delay
shape causes branch 3 to stop executing, allowing branch 4 to execute. Branch 3 is
then executed because the Delay shape has finished and finally once the message for
the Receive shape has arrived, branch 2 is executed to its end.

Another thing to note is, that the Delay shape actually doesn’t make the thread sleep.
If it did, we couldn’t continue in another branch once a Delay shape is run. This
makes perfectly sense, since the shapes in one branch are to be seen as a mini-process
within the big process, and the delay that is needed for that mini-process shouldn’t
affect the other branches. This is exemplified in this process:

image 

The third expression shape in the first branch has been updated to this code:

 1: System.Diagnostics.Trace.WriteLine("1.
3");

 2: System.Threading.Thread.Sleep(2000);

 

image

So as you can see, even though the first branch must wait for 2 seconds, it still
executes completely before the second branch is started.

So, takeaways:

  1. The Parallel Actions shape does NOT mean you get any multi-threading execution environment.
  2. Think of the PArallel Actions shape as a way of letting multiple Business Activities
    happen and you don’t know in what order they will occur.
  3. The Delay shape does not use Thread.Sleep, but instead handles things internally.



eliasen

MSDN Webcast: Improving Business Agility with Enterprise Service Bus

If you have been wondering so far whether an ESB implementation is the right solution for your integration problems, let us help you make the right decision.

On Feb 11th, Peter Kelcey (Technical Sales Professional from Microsoft Canada) and I, will be co-presenting an MSDN Webcast. Peter has extensive experience helping customers with ESB implementation using the BizTalk ESB Toolkit. We will articulate the business values that an ESB brings to integration solutions, specifically how it can promote flexibility and reuse. Being able to adapt rapidly to new business or technical requirements while minimizing development efforts, costs and risks is crucial in the current tough economic climate.

This is going to be a demo intensive session to illustrate with a series of live short demos the advantages and use cases of the BizTalk ESB Toolkit. 
More details are included below as is the link to register. Hope to see you there.

http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032440359&EventCategory=4&culture=en-US&CountryCode=US

Language(s):
English.
Audience(s):
Pro Dev/Programmers. (would be also useful for Enterprise/Solution Architects)
Duration:
60 Minutes
Start Date:
Thursday, February 11, 2010 1:00 PM Pacific Time (US & Canada)

Event Overview
Businesses across the globe are trying to cope with a faster rate of change. The need to adapt rapidly to new internal and external requirements is pushing organizations to look for more flexible solutions to build and connect their applications. At the same time, IT departments are also pressured to reduce costs and reuse software assets and services. Enterprise Service Bus has emerged as an architectural pattern that can help achieve these goals. In this webcast, we introduce the Microsoft BizTalk Enterprise Service Bus Toolkit 2.0 and explain how it accelerates the implementation of a very dynamic and reusable messaging and integration infrastructure on top of Microsoft BizTalk Server 2009 and the Microsoft .NET Windows Communication Framework.

We hope this session will convince you to stop procrastinating and “dive into the ESB pool”

Cheers,

Ofer

Multi-Server ESB Toolkit 2.0 Install (including the Management Portal)

[Source: http://geekswithblogs.net/andym/archive/2010/02/02/137753.aspx]
I recently had the pleasure of installing and configuring the ESB Toolkit 2.0 in a multi-server environment.There are some notes on how to do this in the official documentation but they’re not exhaustive and they don’t include details on how to install the management portal in a multi-server environment.
Prerequisites:
%u00b7 Install and Configure BizTalk in your multi-server environment
%u00b7 Install and Configure UDDI in your multi-server environment:
o You install and configure the Database components on the SQL Server!Yes, your DBAs are going to be unhappy about this.
o Install and configure the other UDDI components on your BizTalk Servers
o If you have a named SQL instance see Raj’s post here in order to get UDDI configured: http://rajsinghblog.wordpress.com/2009/10/26/configuring-uddi-on-a-non-default-clustered-sql-instance/
o Note that you can only run the Notification Service component on server (I assume you could cluster it but we didn’t get into this)
ESB Toolkit 2.0 Installation and Configuration:
%u00b7 Follow the documentation for “Installing the ESB Toolkit Core” on all of your servers
%u00b7 Please note that you can use the “File” configuration in a multi-server environment.To me, it seems that the docs are pushing the “SSO” configuration but you don’t have to use “SSO” for a multi-server environment.Just run the configuration tool on the second to “n” server and point toward the already created databases.Also I have heard that people have had a lot of problems with the SSO configuration
%u00b7 Double check the esb.config file and make sure all of the settings are correct
%u00b7 Watch out for this one during configuration: Exception calling “Create” with “0” argument(s): “Create failed for Login ‘MyDomain\BizTalk Server Administrators’.”See this for how to fix: http://social.msdn.microsoft.com/Forums/en/biztalkesb/thread/5ea700b9-dd91-4dcf-b442-7ada6210f44f
%u00b7 You may need to turn Kerberos on for IIS before you can successfully execute the Microsoft.Practices.ESB.UDDIPublisher.exe: http://support.microsoft.com/kb/215383
%u00b7 Make sure you unpack the samples C:\Program Files\Microsoft BizTalk ESB Toolkit 2.0\ESBSource.zip following the official documentation.(Basically just follow all of the instructions in the “Installing the ESB Toolkit Core” section of the docs
ESB Management portal Installation and Configuration in a Multi-Server Environment:
%u00b7 Keep in mind that the portal is a sample
%u00b7 You can’t use the Management_Install scripts on a server that doesn’t have Visual Studio on it because the scripts require the Visual Studio 2008 SDK to function; the Visual Studio 2008 SDK requires Visual Studio for it to be installed obviously VS won’t be installed in a multi-server environment
%u00b7 The Portals solution (.sln) does include a setup project.I wanted a debug build so I had to open the solution (on my developer workstation)and in Visual Studio and use Configuration Manager to make sure that the setup project would be built for a “debug” build
%u00b7 Build the solution, on your developer workstation,and find the .msi that was created for the portal
%u00b7 Now on each sever in your group, perform the following:
%u00b7 Create an application pool, in IIS, named EsbPortalNetworkAppPool and have it run under Network Service
%u00b7 Install the .msi on your first server; the .msi creates the appropriate Virtual Directories (but doesn’t configure them correctly, see the authentication changes, below); use the application pool you created, when prompted.This creates four virtual directories one for the portal and one for each of its three services.Please note that this installs the portal, the ESB.BAM.Service, ESB.Exceptions.Service and the ESB.UDDI.Services to c:\inetpub\wwwroot
%u00b7 Create the ESBAdmin db using the C:\projects\Microsoft.Practices.ESB\ESBSource\Source\Samples\Management Portal\SQL\ESB.Administration Database.sql file; it blew up at the bottom (find the “Create BizTalk Server Administrators Login” section) because my BizTalk Admin and BizTalk App Users groups were named differently; I manually added the appropriate permissions in SQL Server
%u00b7 Update the C:\Inetpub\wwwroot\ESB.Portal\web.config with the correct db location and group names (connectionStrings and authorization nodes)
%u00b7 Update the C:\Inetpub\wwwroot\ESB.Exceptions.Service\web.config to point to the EsbExceptionDb (connectionStrings node)
%u00b7 Update the C:\Inetpub\wwwroot\ESB.BAM.Service\web.config to point to the BAMPrimaryImport db (connectionStrings node)
%u00b7 Add Windows Integrated to the ESB.Exceptions.Service, ESB.BAM.Service and ESB.Portal virtual directories
%u00b7 Removed Anonymous from ESB.Exceptions.Service, ESB.BAM.Service and ESB.Portal virtual directories
%u00b7 Update the SQL permissions for the ESB Exception Db using the statements found in this thread http://social.msdn.microsoft.com/Forums/en/biztalkesb/thread/1fb510a8-9f4b-4e1e-9261-3273b037786cProps to that guy for banging his head against the wall and figuring out those permissions
%u00b7 Follow the installation and configuration steps for the “Installing the ESB Management Portal Alert Service” and “Installing the ESB Management Portal UDDI Publishing Service” sections.We did this on one server in the group, no more.
%u00b7 We also followed the “Configuring Exception Management InfoPath Form Template Shares” section but I don’t see how that is necessary at this point.
I hope this helps.If I run into issues or I find that I need to correct this post I will update it

Optimizing XML Queries in SQL Server

In creating a process where SQL Server takes XML data that is stored in a table and populates a table, I have learned a few things on how to get SQL Server to more efficiently query XML data.

Setup:

Let’s first create a table to store the data:

CREATE TABLE dbo.XMLDataStore(
  link nvarchar(100) NULL,
  data xml NULL
) ON [PRIMARY]
GO

Let’s take a look at the XML that we are going to query (yes I know is is a large xml document, but I wanted to show the peformance in a real world situation, not a 3 node xml document that is normally demonstrated)

Now let’s insert it into the table:

INSERT INTO [XMLTutorial].[dbo].[XMLDataStore]
           ([link]
           ,[data])
     VALUES
           ('ABCDEFGHIJ'
           ,'<ns0:ORU_R01_231_GLO_DEF xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:ns0="http://labratory/DB/2X">
               ...
            </ns0:ORU_R01_231_GLO_DEF>')
GO

The first query starts at the Observation record (all 64 records) and traverses the xml document and creates the necessary columns in 16 seconds.

select  Observation.ref.value('((../../Patient/PID_PatientIdentificationSegment/PID_5_PatientName/XPN_1_GivenName/text())[1])','nvarchar(100)') as FirstName,
    Observation.ref.value('((../../Patient/PID_PatientIdentificationSegment/PID_5_PatientName/XPN_0_FamilyLastName/XPN_0_0_FamilyName/text())[1])','nvarchar(100)') as LastName,
    Observation.ref.value('((../../Patient/PID_PatientIdentificationSegment/PID_7_DateTimeOfBirth/TS_0_TimeOfAnEvent/text())[1])','nvarchar(100)') as BirthDate,
    Observation.ref.value('((../../Patient/PID_PatientIdentificationSegment/PID_2_PatientId/CX_0_Id/text())[1])','nvarchar(100)') as InsuranceNumber,
    Observation.ref.value('((../OBR_ObservationRequestSegment/OBR_1_SetIdObr/text())[1])','nvarchar(100)')as [OBRID],
    Observation.ref.value('((../OBR_ObservationRequestSegment/OBR_7_ObservationDateTime/TS_0_TimeOfAnEvent/text())[1])','nvarchar(10)') as ObservationDate,    
    Observation.ref.value('((../OBR_ObservationRequestSegment/OBR_4_UniversalServiceId/CE_1_Text/text())[1])','nvarchar(100)') as LabTestName,
    null as LabTestCode,
    Observation.ref.value('((./OBX_ObservationResultSegment/OBX_1_SetIdObx/text())[1])','nvarchar(100)') as [OBXID],
    Observation.ref.value('((./OBX_ObservationResultSegment/OBX_3_ObservationIdentifier/CE_4_AlternateText/text())[1])','nvarchar(100)') as LabResultName,
    Observation.ref.value('((./OBX_ObservationResultSegment/OBX_3_ObservationIdentifier/CE_0_Identifier/text())[1])','nvarchar(100)') as LabResultCode,
    Observation.ref.value('((./OBR_5_PriorityObr/text())[1])','nvarchar(100)') as [Priority],
    Observation.ref.value('((./OBX_ObservationResultSegment/OBX_14_DateTimeOfTheObservation/TS_0_TimeOfAnEvent/text())[1])','nvarchar(100)') as [ResultDate],
    Observation.ref.value('((./OBX_ObservationResultSegment/OBX_5_ObservationValue/CE_4_AlternateText/text())[1])','nvarchar(100)') as [ResultValue],
    Observation.ref.value('((./OBX_ObservationResultSegment/OBX_6_Units/CE_0_Identifier/text())[1])','nvarchar(100)') as [UnitOfMeasure],
    Observation.ref.value('((./OBX_ObservationResultSegment/OBX_7_ReferencesRange/text())[1])','nvarchar(100)') as [ReferenceRange]
from XMLDataStore x cross apply x.data.nodes('//Observation') Observation(ref)
where x.link='ABCDEFGHIJ'

The first optimization step is instead of using the Observation node and deriving all of the other columns from that, you can further use CROSS APPLY to create separate nodes to extract data from coupled with not using wild cards and diving directly to the exact node I need to. I went to the OBX_ObservationResultSegment as the originating node, and then from that node (named Observation), I derived two other nodes to reference in the query; Patient and Request.

This time the query completed in 4 seconds:

WITH XMLNAMESPACES ('http://labratory/DB/2X' AS "ns0")
select  Patient.node.value('(PID_5_PatientName/XPN_1_GivenName/text())[1]','nvarchar(100)') as FirstName,
    Patient.node.value('(PID_5_PatientName/XPN_0_FamilyLastName/XPN_0_0_FamilyName/text())[1]','nvarchar(100)') as LastName,
    Patient.node.value('(PID_7_DateTimeOfBirth/TS_0_TimeOfAnEvent/text())[1]','nvarchar(100)') as BirthDate,
    Patient.node.value('(PID_2_PatientId/CX_0_Id/text())[1]','nvarchar(100)') as InsuranceNumber,
    Request.node.value('(OBR_1_SetIdObr/text())[1]','nvarchar(100)')as [OBRID],
    Request.node.value('(OBR_7_ObservationDateTime/TS_0_TimeOfAnEvent/text())[1]','nvarchar(10)') as ObservationDate,    
    Request.node.value('(OBR_4_UniversalServiceId/CE_1_Text/text())[1]','nvarchar(100)') as LabTestName,
    null as LabTestCode,
    Observation.node.value('(OBX_1_SetIdObx/text())[1]','nvarchar(100)') as [OBXID],
    Observation.node.value('(OBX_3_ObservationIdentifier/CE_4_AlternateText/text())[1]','nvarchar(100)') as LabResultName,
    Observation.node.value('(OBX_3_ObservationIdentifier/CE_0_Identifier/text())[1]','nvarchar(100)') as LabResultCode,
    Observation.node.value('(OBR_5_PriorityObr/text())[1]','nvarchar(100)') as [Priority],
    Observation.node.value('(OBX_14_DateTimeOfTheObservation/TS_0_TimeOfAnEvent/text())[1]','nvarchar(100)') as [ResultDate],
    Observation.node.value('(OBX_5_ObservationValue/CE_4_AlternateText/text())[1]','nvarchar(100)') as [ResultValue],
    Observation.node.value('(OBX_6_Units/CE_0_Identifier/text())[1]','nvarchar(100)') as [UnitOfMeasure],
    Observation.node.value('(OBX_7_ReferencesRange/text())[1]','nvarchar(100)') as [ReferenceRange]
from XMLDataStore x 
cross apply x.data.nodes('ns0:ORU_R01_231_GLO_DEF/CompleteOrder/Order/Observation/OBX_ObservationResultSegment') Observation(node)
cross apply Observation.node.nodes('../../../Patient/PID_PatientIdentificationSegment') Patient(node)
cross apply Observation.node.nodes('../../OBR_ObservationRequestSegment') Request(node)
where x.link='ABCDEFGHIJ'

Never being satisfied, let’s add an index to the data. However, to add an xml index to the data, we need to create a clustered index on the table. If we simply try to add an xml index to the current table with this command:

CREATE PRIMARY XML INDEX PrimaryXMLIndex ON
dbo.XMLDataStore(data)
GO

We get the following error:

Msg 6332, Level 16, State 201, Line 1
Table 'dbo.XMLDataStore' needs to have a clustered primary key with less than 16 columns in it in order to create a primary XML index on it.

Not descriptive, so let’s create a new table:

CREATE TABLE dbo.OptimizedXMLDataStore(
  id INT IDENTITY PRIMARY KEY,
  link nvarchar(100) NOT NULL,
  data xml NOT NULL
) ON [PRIMARY]
GO

And creating the following indexes in the database:

CREATE PRIMARY XML INDEX PrimaryXMLIndex ON
dbo.OptimizedXMLDataStore(data)
GO
CREATE XML INDEX
XMLDataStore_XmlCol_PATH ON dbo.OptimizedXMLDataStore(data) 
USING XML INDEX PrimaryXMLIndex FOR PATH
GO

Now that the indexes are created, let’s insert the data into this table:

INSERT INTO [XMLTutorial].[dbo].[OptimizedXMLDataStore]
           ([link]
           ,[data])
     VALUES
           ('ABCDEFGHIJ'
           ,'<ns0:ORU_R01_231_GLO_DEF xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:ns0="http://labratory/DB/2X">
               ...
            </ns0:ORU_R01_231_GLO_DEF>')
GO

Now let’s run the same query (except pointing to the indexed table):

WITH XMLNAMESPACES ('http://labratory/DB/2X' AS "ns0")
select  Patient.node.value('(PID_5_PatientName/XPN_1_GivenName/text())[1]','nvarchar(100)') as FirstName,
    Patient.node.value('(PID_5_PatientName/XPN_0_FamilyLastName/XPN_0_0_FamilyName/text())[1]','nvarchar(100)') as LastName,
    Patient.node.value('(PID_7_DateTimeOfBirth/TS_0_TimeOfAnEvent/text())[1]','nvarchar(100)') as BirthDate,
    Patient.node.value('(PID_2_PatientId/CX_0_Id/text())[1]','nvarchar(100)') as InsuranceNumber,
    Request.node.value('(OBR_1_SetIdObr/text())[1]','nvarchar(100)')as [OBRID],
    Request.node.value('(OBR_7_ObservationDateTime/TS_0_TimeOfAnEvent/text())[1]','nvarchar(10)') as ObservationDate,    
    Request.node.value('(OBR_4_UniversalServiceId/CE_1_Text/text())[1]','nvarchar(100)') as LabTestName,
    null as LabTestCode,
    Observation.node.value('(OBX_1_SetIdObx/text())[1]','nvarchar(100)') as [OBXID],
    Observation.node.value('(OBX_3_ObservationIdentifier/CE_4_AlternateText/text())[1]','nvarchar(100)') as LabResultName,
    Observation.node.value('(OBX_3_ObservationIdentifier/CE_0_Identifier/text())[1]','nvarchar(100)') as LabResultCode,
    Observation.node.value('(OBR_5_PriorityObr/text())[1]','nvarchar(100)') as [Priority],
    Observation.node.value('(OBX_14_DateTimeOfTheObservation/TS_0_TimeOfAnEvent/text())[1]','nvarchar(100)') as [ResultDate],
    Observation.node.value('(OBX_5_ObservationValue/CE_4_AlternateText/text())[1]','nvarchar(100)') as [ResultValue],
    Observation.node.value('(OBX_6_Units/CE_0_Identifier/text())[1]','nvarchar(100)') as [UnitOfMeasure],
    Observation.node.value('(OBX_7_ReferencesRange/text())[1]','nvarchar(100)') as [ReferenceRange]
from OptimizedXMLDataStore x 
cross apply x.data.nodes('ns0:ORU_R01_231_GLO_DEF/CompleteOrder/Order/Observation/OBX_ObservationResultSegment') Observation(node)
cross apply Observation.node.nodes('../../../Patient/PID_PatientIdentificationSegment') Patient(node)
cross apply Observation.node.nodes('../../OBR_ObservationRequestSegment') Request(node)
where x.link='ABCDEFGHIJ'

The results came back in 0 seconds

Things I did not do:

  1. Actually see Clark Kent (I think he was born before June of 1938, but it was the first time he was writtent about)
  2. Question why the “The Last Son of Krypton” was actually getting lab work done
  3. Imported schemas into the database