Capturing BizTalk 2006 BAM Data On Looping Process

Published 29 March 06 10:30 AM | rseroter 

While working on a BizTalk POC last week, I needed to track Business Activity Monitoring (BAM) data across looping iterations and had to set up relationships between activities. I wanted to share the steps below.

This is the same POC mentioned in my post two days ago. It's a Change Request scenario where we get a Change Request from SharePoint, and start a workflow to get that Request both approved and acted upon. The approval notice is sent to multiple individuals, who each approve or deny the Request. So, as you can see, it would be of great importance to be able to track response time for each approver, accept/deny trends, and so forth. But since the BAM Primary Import table is fairly flat, how do you track these iterative responses, without resorting to having node/BAM values for "Approver1, Approver1Response, Approver2, Approver2Response" and so forth?

The first thing to do (after the project has been built) is to create a BAM definition file. I created mine in Excel using the BAM add-in, and exported the settings to XML. As you see in my file below, I've defined two separate Activities: ProcessNewChangeRequest and ProcessApprovalResponse. The first is for tracking the greater, parent change request process, and the second is for each approval response we get back from an individual. After the definition is done, deploy it using the BAM Management Tool (bm.exe).

Next step is go into the orchestration(s) and explicitly populate the BAM data at strategic points. Using the BAM API is the alternate to use the Tracking Profile Editor (TPE). There's pros and cons for both, and in my case, the flexibility of the API won over the ease of use of the TPE. Add a reference to the Microsoft.BizTalk.Bam.XLANGs assembly. The orchestration starts like this ...

You need to make a decision from the start as to WHICH of the various BAM streams you wish to use. You can see some nice comparisons of options HERE, HERE, and HERE. Basically, Buffered Event Stream collects the data up and publishes it to the BAM service, which in turn populates the database. The Direct Event Stream goes directly to the Primary Import table, which is slower, but you get notification if something fails vs. the async nature of the Buffered Event Stream. The Messaging Event Stream is for pipelines, and not used here. The last choice is the one I used: Orchestration Event Stream. This one commits the data as the orchestration does, is fairly easy to use, and doesn't require a connection string parameter. It's not documented in the least, but inherits from EventStream and has a similar API.

So, my first BAM Expression Shape starts up the process. The code in the Shape starts with a BeginActivity, which takes in the name of the Activity (in our case, ProcessNewChangeRequest) and, a unique identifier to mark this instance throughout it's lifetime. I used the unique RequestID field of my message. After starting the activity, I then executed an UpdateActivity which accepts the Activity Name, which instance to update (using unique ID), and then list of name/value pairs of data/milestones to update.

I then perform UpdateActivity a couple more times with data acquired at various steps. Next big thing is calling another orchestration which controls the process loop that receives Approver response messages. So, I do a sync Call Orchestration and pass in a few messages plus the unique ID, and, get a StatusCode and final message out.

This second orchestration sends out messages for email, and, loops through responses that get returned. The key thing here was to create a *new* Activity instance for each loop, and tie that back to the original caller. In the loop, I first populate a variable for a unique ID (that gets reset on each loop), and then have an Expression Shape that does a BeginActivity, passing in the Activity name (in this case, ProcessApprovalResponse), and the unique ID. I then do an UpdateActivity and pass in values from our message that came back from an Approver.

At the end of the loop we do two things. First, I called AddRelatedActivity, passing in the current Activity name (ProcessApprovalResponse) and ID, and then, the parent Activity name (ProcessNewChangeRequest) and the unique ID of the parent instance (passed in as an orchestration parameter). What does this do? Populates the <activityname>_Relationships table which creates an association between these activities. Finally, I called EndActivity to close the process. Back in the calling orchestration, I also call EndActivity when all responses are received and the Change Order process is completed.

So what does the result look like? In the BAM Portal, I can search for various Change Requests ...

If I click on a given row, I'm taken to the Details page. Notice at the bottom, I have two Related Activities. Here's where we see that association we made from the orchestration!

If I click a RelatedActivity, I get the Details page for that Approval activity, and a link back to my parent process under Related Activities.

So, very nice functionality and reporting, without a whole lotta work. If you're loving this topic, don't forget to check out Darren Jefford's recent post and tool for putting a more elegant facade over the BAM API. Enjoy.

Filed under:
Anonymous comments are disabled
Page view tracker