News

My Stats

  • Posts - 26
  • Comments - 25
  • Trackbacks - 55

Twitter










Recent Comments


Recent Posts


Archives


Post Categories



CharacterTranscoder is a BizTalk pipeline component + stream class that can transcode a stream from a configurable source encoding to a configurable target encoding.

The source is now available on github.com.
Git takes some time to get used to.
I managed to put something online somehow, which means everybody should be able to :-)

Microsoft also offered a free support case for the FFASM bug and the behavior is already reproduced at their side. Nice!


In order to get the FFASM encoding bug looked at, Microsoft Support asked me to call an 0800 number and provide payment info :-(

Since I am still convinced every bug should be reported I will try again next month when I have my client's support contract details (the guy with the info is on a very long summer holiday :).

In the mean time I have developed a custom fix which you may use at your own risk...

This TranscodingStream class is a binary transformation stream decorator: while reading, the underlying bytes are transcoded on the fly from a source to a target encoding. Both source and target encoding are configurable.

You can make your own pipeline component that replaces the incoming message its bodypart stream by this TranscodingStream (and a context property to dynamically set the target encoding). In fact I have built it already, if you want it just let me know.

This way you can leave the FFASM to its default (UTF8) and let this new component do the work right-after. Also mind that the TranscodingStream doesn't prefix a BOM, which could be problem for UTF-16 (for the simple reason I didn't need it, like in YAGNI).

In retrospect my stream decorator could have been done a bit better. It violates the single responsibility principle since it does decoding + encoding in 1 step. This explains the Read's method cyclomatic complexity being too high. A cleaner design would have been: DecodingStream decorator that translates whatever source encoding to Unicode + EncodingStream decorator that translates Unicode to whatever target encoding. 


Or how to fix a bug while introducing another one that's a lot nastier. Let's start by describing the original bug: the BizTalk flatfile assembler has issues with custom target (output) encodings.

When compiling a custom pipeline with the FF assembler and configuring the 'target charset' in the pipeline designer everything works as expected and you will get your messages in the desired encoding.

When you want to dynamically control the encoding, according to the docs, you should also be able to do this by writing the XMLNORM.TargetCharSet property onto the message context.

In my case the desired output was 'Windows-1252'.

I was able to verify that this technique indeed works using a default XmlTransmit assembler pipeline.
With a custom FF assembling pipeline though I got a question mark in the flatfile output for every special character.
 
Since the only differentiator being the pipeline I am quite confident that it's a FFASM assembler bug.

Now to come to the second problem: apparently this bug was already discovered over a year ago and I guess it was never reported to Microsoft (since it is still not fixed in BTS 2009, the RC I checked). It might be a regression since people reported that it only happens from version 2006 R2.

Instead, the author decided the shortest path to success was to develop a custom encoding pipeline component that takes care of the output encoding. The issue showed up a few more times since then and it looks like other people were inspired by his workaround.

Now take a good look again at how the author implemented the custom encoding. There is something terribly wrong with it.

HINT: the input encoding is UTF-8, a variable byte length encoding. Inside the loop a fixed number of bytes is read from the input. Got it?


Recently we have been receiving another series of complaints from clients that had trouble reading the pdf attachment of a BizTalk dynamic generated email. For some years we have been using the MIME encoder pipeline component and dynamically buildup our emails as multi-part message from inside orchestration. We got the mustard from here.

As said, it wasn't the first time we had these complaints. But it was always for a small minority of users only. Hence it sounded more like a user-specific issue. Since the smoke kept coming back I decided to start looking for a small fire at our side. Which I think I found:

By default the MIME encoder pipeline component puts 'text/plain' as the MIME content-type. This will always work if your content is in fact of type 'text', but for all the other types such as a pdf it is not correct in the strict sense.

Success will depend on the mail-client: apparently GMAIL doesn't care that much about it, same story for the majority of our Exchange/Outlook clients. If you want 100% coverage, the only good solution is to specify the correct MIME type for every attachment. For a pdf attachment it should be 'application/pdf':
 



Please note that the BizTalk 2006/2009 SMTP adapter can take care of the correct MIME encoding (but if the content is already MIME encoded inside the pipeline it is kept intact). According to various blog entries the new SMTP adapter's MIME encoder will take care of setting the correct content-type.

I preferred a small update to my existing code instead of a global rewrite to leverage these new options.
Luckily you can override the MIME encoder's default by specifying the content type of the XLANGPart like this:


part.SetPartProperty(typeof(Microsoft.XLANGs.BaseTypes.ContentType), contentType);

The only thing left to-do is to find out the correct MIME-type per attachment. I have wrote a small function that does exactly that by using the file extension:















etc...


The default content-type for unknown extensions is "application/octet-stream".
This alone could have been enough to fix the issue but I've tried to put in as much detail and content-types as are documented here.

Here is a sample class (original sample credits go to Tomas Restrepo with content-type update).


The previous BAM portal post reminded me of some BAM classes I re-use but never blogged about...
 
Here is my small-scale proven semi-automated alternative based on the mapper pattern and nullable fields.

The core functionality comes from a 'BAM gateway class' which is composed with a IMapper<A,B> instance, responsible for mapping strongly typed activities to an object array. This object array contains the activity property names and corresponding values just like the eventstreams likes them, ready to be writen. Here is my favorite mapper:

public class NonDefaultValuesMapper : IMapper<IActivity, object[]>

It is generic in the sense that it just checks if the activity instance properties are set or not. It also maps class' property-name to the activity field-name. The activity class of-course has to support this and use nullable fields/properties for the value typed fields.

For every activity I write a state-only class that derives from my IActivity interface (a DTO object if you like).

public class TrainWaybillActivity : IActivity
{

    const string _activityName = "TrainWaybill";

    string _activityId;

    public TrainWaybillActivity(string activityId)
    {
            this._activityId = activityId;
    }

    string FromStationName { get;set;}
    string ToStationName { get;set;}

    DateTime? Start { get;set;}
    DateTime? Sent { get;set;}
    DateTime? Approved { get;set;}
    DateTime? Denied { get;set;}
    DateTime? Ready { get;set;}

}

A gateway class (per activity) contains specific methods which cover all activity interaction necessary and that all BAM clients must use.

Some of the gateway methods are intended for orchestration and accept a class based message parameter (created with xsd.exe, for XmlSerializer).


class TrainWaybillActivityGateway
{
    public readonly string _activityID;    
    IActivityWriter _writer;
    private IMapper<TrainWaybillActivity, object[]> _fieldMapper;
    private IMapper<IFTTOI, TrainWaybillActivity> _mapperIFTTOI;
    private IMapper<APERMS, TrainWaybillActivity> _mapperAPERMS;

    public void Start(IFTTOI waybill) {}

    public void WaybillSent() {}

    public void SetAcknowledged(APERMS acknowledgment)
}

This way messages can be passed in and be used to extract activity field values.
I again use the mapper pattern for transforming messages to activities (such as IMapper<APERMS, TrainWaybillActivity>).

I also wanted the gateway classes to be universally usable: from orchestration, pipelines as well as from custom code.
Therefore BizTalk has different evenstream classes with different behavior targeting different scenarios.
Unfortunately they do not all derive from a common base EventStream interface so in order to make the gateway universal I had to create a custom 'IEventStream' interface. I had to create these 2 adapters:

The OrchestrationEventStreamAdapter delegates calls to the BizTalk static OrchestrationEventStream methods.
The EventStreamAdapter is composed with a BizTalk EventStream instance and delegates all calls to this instance.

The OrchestrationEventStreamAdapter has an empty Flush() implementation. It also throws an exception when  StoreCustomEvent is called. I could have removed this method from the interface (especially because I have no clue why anybody would want to use it). From MSDN documentation I learned that custom events are objects of type DelayedSpCall: A serialized stored-procedure call, which is just a form of a serialized command-object, queued for later execution (by the event bus in this case). Anybody??
 
This approach was used on several small-scaled BAM projects (well, large projects with small BAM requirements).
I am not sure if things have moved on since the GenerateTypedBAMAPI xsl based code generator.
Maybe I should make a generator too?

All feedback is welcome.
If the picture is not totally clear: here is some code.


Yesterday I've tried to reproduce the scenario 'Configuring a Static Port to Behave as a Dynamic Port' from the excellent MSDN article 'Consuming and Hosting WCF Services with Custom Bindings in BizTalk Server' but with a twist: instead of writing the BTS.OutboundTransportLocation context property inside a custom pipeline component I've tried doing this from inside orchestration.

It didn't work. I had to do it differently. Let me explain...

If you manually promote a custom value for the BTS.OutboundTransportLocation on your outgoing message inside an orchestration message construct and send the message to a static send port, the BTS.OutboundTransportLocation property is magically overwritten with the address from the statically configured send port. The fact that this property is automatically set by the engine seems logical because it is necesarry for a regular static send. I only hoped it wouldn't be overriden when already present. 
Why magically? Because it doesn't show up like that in HAT! If you look into HAT the message-context 'before pipeline execution' you can see that the custom value is there: it was successfully written to the context inside the orchestration.
But by adding some traces to a dummy pipeline component I can CONFIRM that those custom values are indeed already erased and reset to the address from the send port configuration @pipeline-execution. This indicates that there is an additional step after tracking and before the adapter triggers the pipeline execution, where the engine adds all sorts of properties from the port configuration. So e
ven when you are using a passthru send pipeline the message 'after pipeline execution' has a different context then 'before pipeline execution'. Another clear case of opacity ;-) And that's where my confusion came from. One might wonder why they didn't choose to track the 'before pipeline execution' right after the engine added its properties. There is probably a good reason for that...

Anyway, I needed to take a step back and reconsider the approach from the article ie setting the value inside a pipeline component. But hardcoding or configuring an address inside a pipeline isn't really 'dynamic'.

So here is the final piece of the puzzle:

Roll in your own 'address' property that is written on the message context inside orchestration and is re-written into the BTS.OutboundTransportLocation property during pipeline execution.


For a couple of years I have been tracking message-bodies inside BAM but only recently I was asked to make a BAM Portal document link to these message bodies that actually works :-)
Strangely enough I couldn't find any solution on Google so I tried to figure this one out myself. Guess what? I had to jump through quite a few hoops. I decided to share those hoops with my other 2 blog readers (yes you).


  • Hoop 1: the 1st and most obvious step is getting the message bodies into the BAM tables using the eventstreams. This can be done using the AddReference method. 

es.AddReference(activityName, activityID, referenceType, referenceName, referenceData, longReferenceData);


Put the body string inside longReferenceData and freely choose your referenceType and referenceName. Making referenceType unique comes in handy later because you can query on a specific referenceType thru the web service (and not on referenceName).   

You should now have your body inside the BAM table (check: bam_{activityName}_AllRelationships). You can easily query his table via the BAM Management web service like this:

web service










  • Hoop 2: You need to find a way to query the BAM management web service for a specific reference through a simple link instead of a http post soap request.

Jesus and Joe's great BAM paper suggest a restful API which sounds great but unfortunately isn't a fact yet. My workaround consists of httpget-enable the web service. Adding this snippet inside the system.web section of the web.config file in the folder C:\Program Files\Microsoft BizTalk Server 2006\BAMPortal\BAMManagementService will get you exactly that:

    <webServices>
        <protocols>
            <add name="HttpGet"/>
        </protocols>
    </webServices>

Now the web service sample invoke page will also show a sample 'get' request:

asmx sample











  • Hoop 3: You need to put a link to the http get url as a 'document link'  on the BAM portal. You can do this again via the stream by adding a reference of type 'DocumentUrl'  and putting the relative link inside the referenceData field.

es.AddReference(activityName, activityID,
'DocumentUrl', referenceName, referenceData, "");
My link string format looks like this:

string link =
            string.Format(
            "/bam/bammanagementservice/bammanagementservice.asmx/GetReferences?viewName={0}&activityName={1}&activityInstanceId={2}&referenceType={3}",
            "put your activity view name here",
            "put your activity view name here",
            "activityID here",
            "referenceName here");



That's about it.


This post is about Finite State Machines, the Flying Spaghetti Monster is for next time.

For one of the EAI projects I'm working on I needed a specific StreamReader that adds field-wrappers (around the fields, obviously) of a char-based stream. For example:

field1-1,field1-2;field2-1,field2-2 => "field1-1","field1-2";"field2-1","field2-2"

My first approach was the currently popular test-driven one: a default passthru read method and a bunch of tests, that of-course all initially failed. I trusted my creativeness in order to randomly identify all different types of input-string combinations:

NoFieldSeperator
NoRecordSeperator
EmptyString
FieldWithSingleWrapCharInfix
FieldWithSingleWrapCharPostfix
etc...

Inside the reader I added different if-then-else clauses to manipulate the output, until a given test succeeded. Every newly added if-clause of course potentially broke 1 or more of the previous tests. One can imagine it took quite a lot of time and way too many iterations to get this very simple parser working!

After a while I was lucky enough to get all cases working: hurray! In fact, not really :-(
I didn't have complete confidence in what I had just built and how it was built. This wouldn't work for more complex scenarios. How could I ever be sure that I didn't forget some special case? I needed a more formal approach...
 
So I modeled the reader as a finite state machine, thereby defining the actions i.e. the desired output character(s) for every input character depending on the state. It's very easy, just start drawing on a piece of paper and think about the states and the output for every input. The reader can be in the 2 following states: 'inside a field' or 'outside a field'.


I have defined 'special' input tokens that require special handling (different action) or trigger a state transition:

RD: record delimiter
FD: field delimiter
WS: whitespace
EoF: end of file
WC: wrap character
C: any other char

The output (or action) for a given input greatly depends upon the state the reader is in and if the input character triggers a transition. EoF, field- and record-delimiters trigger a state transition from insidefield to outsidefield.

I didn't put the actions on the diagram. 
For every 1 char in the input, the reader can output 0, 1 or 2 chars. If the input contains the field-wrap character inside a field, it should be doubled. This requires the ability to cache a few characters.

field1,fiel"d2; => "field1","fiel""d2"

Whitespaces could be configured to be skipped if non-significant (trimming).
Also RD or FD when 'OutsideField' could be configured to generate empty fields.
For this implementation I choose the object-oriented state design pattern.


internal abstract class StreamState
        {
            public abstract int CharInput(WrappingFsmStreamReader context, int character);
            public abstract int WhitespaceInput(WrappingFsmStreamReader context);
            public abstract int FieldDelimiterInput(WrappingFsmStreamReader context);
            public abstract int RecordDelimiterInput(WrappingFsmStreamReader context);
            public abstract int WrapInput(WrappingFsmStreamReader context);
            public abstract int EoFInput(WrappingFsmStreamReader context);
        }

Here is a sample.

So next time you need a custom StreamReader it makes sense to model it as a FSM. Define and document the states and behavior, use this inside knowledge to write the unit tests.


My motivation for this post comes from the fact that I could only find 1 blogpost related to BizTalk and DI: it was about DI using Spring.net and late binding, and it was in fact rather about SL. I'm not pretending to be an expert on the subject but a second blogpost with a little bit of background on the subject of dependency resolution in the context of BizTalk can surely make a difference...


When developing O.O. components there are 2 popular patterns for organizing your objects' dependencies in an elegant way:


1. service locator pattern aka 'dependency pull': your library objects explicitly make a call to a pre-configured locator-component in order to resolve all dependencies.


2. dependency injection: your library objects' missing dependencies are part of the public interface and are automatically managed and injected by an IoC container that you specifically configure per client application, which is referred to as 'wiring up' the components.

There are multiple variants of how the injection can happen: setter based= properties are set automatically, constructor based=missing constructor parameters are resolved automatically, etc...


Also, to further complicate things, you might be tricked into thinking you are doing proper DI because you are using a DI framework while you are in fact applying the locator pattern. In reality you could might as well be abusing your container by letting your objects pull out dependencies from it directly, via a hard-coded reference to the container, or via service locator gateway to the container. Then you are in fact doing service location, regardless of the container framework.


Theoretically though, both patterns are different and purists say that in practice a clean design should choose 1 of both and stick to the choice. Personally, I totally agree...

 

Others are convinced they have valid reasons to exceptionally break this rule.

For example some prefer using constructor-based dependency injection for all concern-specific dependencies + exceptional service location for all your 'infrastructure dependencies'. The main reason for this is trying to have at least as possible setters or constructor parameters for cross cutting concerns, which would otherwise only obfuscate the self explaining nature of a nice clean O.O. object. Logging could for-example be considered a cross cutting concern which you'd rather not have an interface for in every other constructor.


This way the constructors remain mostly clean, but you still end-up with 1 non-concern specific parameter-constructor or setter (for passing the service locator). The static gateway pattern as described and explained in great detail by JP Boodhoo is a nice testable solution for not having to pass around a service locator to every object in your model, while not having to revert to hard to test singletons.


When creating an über static gateway, the ServiceLocatorGateway (JP calls it the 'DependencyResolver', here and here), you can 'completely eliminate the need for static fields and initialization method in about everything but the main Static Gateway itself' to use his words. His sample also has a method for registering components.

Again, some purists say it is still bad to have occasional service location when primarily relying on DI. 

If you'd still want to do mainly dependency injection with only occasional service resolution, then the locator should only serve as a gateway to the container. You would prefer a service locator with no support for registration. You should also never reference a specific container framework directly from a service locator implementation. Define a service locator interface. The CSL, CommonServiceLocator, can be used as an extra level of separation and is the best option.

This way you don not force clients to use a specific DI framework and they can benefit from a ready-made CSL specific adapter for most of the DI frameworks.


Unfortunately static gateways, as well as any other library-scoped static variable, will not always play nice along BizTalk.

Since all BizTalk artifacts such as orchestrations and all referenced libraries are deployed to and are run by a single logical application, the XLANG engine hosts,  everything that gets loaded will run inside the same application domain by default (yes, I know this can be changed through xml configuration) and will be static for the whole collection of BizTalk apps.

So static gateways work well with 1 BizTalk app but as soon as 2 BizTalk applications both reference the same library, both will call 'InitializeWIth' (or similar) and they will override each others' settings at runtime.


If you are forced to use a third party library relying on a static gateway, and you need to find a workaround/hack to make it work with multiple BizTalk apps without changing the global xml config: I'v got a sample workaround (BTS2009, VS.NET2008). I have defined a ServiceLocator decorator for CSL that adds some dynamic reflection-based behavior: the call-stack is walked to find a specific ServiceLocator implementation that was registered for the assembly calling the library. Of course this has a performance-impact. Of course, it is only sample...


        /// <summary>

        /// When the library depends on static initialization by multiple BizTalk Apps,

        /// make sure every BizTalk application decorates using the AssemblyServiceLocator

        /// </summary>

        /// <returns></returns>

        public IServiceLocator GetAssemblyServiceLocator()

        {

            return new AssemblyServiceLocator(GetServiceLocator());

        }


The correct functionality of DI also relies on the fact that the caller 'wires up' the components, and that you have an 'entry point' into the container: a boot object is retrieved from the container with a Start() method. But not so in case of BizTalk.

BizTalk artifacts are service hosted and fired without you having very much control over it.

How exactly depends on the type of Biztalk component: a pipeline component, a receiver / send adapter or in most cases: an orchestration instance. So what if you were handed over a shared library that relies on the caller for its DI container configuration, and you need to use it from an XLANG?


An orchestration instance is externally managed and can dehydrate and rehydrate after a host instance restart (or maybe inside another host instance on a different server). So when to initiate a service locator or to wire up the IoC container?


Since we haven't got any obvious entry point for an orchestration you need to create multiple 'static entry points' and use the library in a stateless manner to be on the safe side. At most you could optimize by making the container a static.

Route all calls from your orchestration to your library, via a solution-specific gateway class and put the container creation code inside the static initializer, which is guaranteed to run once per application domain. You need to mirror all the library methods you want to call from XLANG, and instantiate library-variables by using the static container variable (or alternatively create the container and dispose of it for every method in the wrapper, which will have a bigger performance impact; another option is to create inner containers in case of autofac). 


What about using container-managed instances as orchestration variables? Is this safe? I don't know...

If the library also relies on a client side statically initialized SL: after rehydration the locator won't be initialized by default to start with. Some containers can also generate 'factory' delegates (which forward an object creation request to a constructor, filling in all missing parameters from whats defined in the container) which might be a problem. 

I have tried to make the container an orchestration instance variable to keep the wiring intact after runtime serialization...but then you would have to pass this into the wrapper class for every method call. So it needs some further investigation.


As usual a little disclaimer:

There is no guarantee whatsoever and nothing has been thoroughly tested.



Astute readers might have noticed I have switched to a more narrow skin named  'Leafy skin'. That, of course, is not a coincidence. This technically lightweight blog posting, apart from its subject, also serves a hidden agenda:  scraping the dust of my rusty old blog. Thanks to this updated skin and by ensuring the first post showing up is dated from 2008, it is my goal to mislead many of you who never take the time to scroll down and check the date of the post just underneath.


line feed,


line feed,


line feed,


give it up.


To the subject of the day.


Find a friend that has switched to the white side. He might be able to help you create a self signed certificate with his certificate assistant in Mac Os X keychain that works for BizTalk.


Apparently BizTalk is very picky about the key usage extensions (or the extended key usage extensions, don't know). I couldn't get it working right-away using the command line tools on my Windows machine. So I gave it a try on my Mac:




And the AS2 connections just worked, no more complaints.


All the Biztalkers that don't have Apple friends and need an AS2 certificate that works may drop me an email. I can sell those private keys on Ebay later on, for a good cause :-)



The BizTalk 2006 version and API is 100% backwards compatible with the 2004 version and API. BizTalk 2006 is built against .NET2.0 while the BizTalk 2004 assemblies were built against .NET1.1. Although I’m not working for Microsoft this surely means that for the BizTalk 2006 version the Microsoft BizTalk product team has:
 
1. Checked the re-used BizTalk 2004 code parts against the new .NET version for incompatibilities and resolved all of them for the BizTalk 2006 release
.

2. Rewritten parts of the original BizTalk 2004 implementation in order to benefit from the new framework version (such as a performance gain) without breaking compatibility with the previous BizTalk version.

3. Added a lot of new BizTalk functionality written from scratch in .NET2.0 code.

In general .NET framework supports installing and running different framework versions side-by-side on a single machine. By default your custom old .NET1.1 applications will run with .NET2.0 when you run them on a machine with 2.0 installed. If you detect incompatibilities you can instruct .NET to load the old runtime version you originally built your application against (by means of configuration). Or you can choose to fix the incompatibility in your code and recompile for .NET2.0.

Whole different story for your newly written .NET2.0 applications: they only run with 2.0 or higher compatible version (for example 2.1). 

Microsoft BizTalk 2006 is a ‘new application’ and is ‘built against’ .NET 2.0 (beta) and as a consequence will only run with .NET framework 2.0 or higher compatible version. The BizTalk 2006 host instances will load and execute code using CLR .NET2.0 and as a consequence the assemblies it loads will execute within .NET 2.0. Your assemblies used inside orchestrations, your custom adapters and your pipeline components and their dependencies will all have to be compatible with .NET2.0. You don’t have the option to instruct to load the .NET framework version you built your assembly against because loading 2 different CLR versions in the same process is not supported. Here is a good post from Junfeng Zhang about the subject: The CLR Side by Side and Compatibility.

This means that as a BizTalk developer you should at least perform step 1 from the above steps for all your BizTalk 2004 custom code. If you’re lucky you detect no incompatibilities and it will work by default. But if you do detect incompatibilities then you’ll have to re-code and re-compile. For more information on the .NET CLR see Suzanne Cook’s weblog



The SDK of BizTalk 2006 Beta2 will include a new version of the adapter base classes. These will not be backwards compatible with the original BizTalk 2004 SDK classes.

The API has changed and the internals have changed (uses System.Transactions for example). Adapters that have been originally built with the 2004 adapter base classes should continue to use and be deployed with this version.The .NET1.1 compiled assembly of the old base classes should by default work with.NET2.0 CLR.

You could of course prefer to re-compile for .NET2.0 but you will get some warnings during compilation time.



Although I'm still recovering from an earlier *shock* (from when I received the totally awesome MVD award), I'm proud to announce that as of this month I'm a genuine, fully-fledged Microsoft MVP for BizTalk Server. This is really fantastic!



For those who are wondering why I’m not blogging very regularly: It’s not that I’m lying on my back and sun-bathing on the beach or anything (which was never been an option since it has been snowing a lot), I'm just rather busy lately. I was doing a SP1 evaluation earlier, for which MS has granted me a prestigious award for ‘Most Valuable Debugger’. It’s a kind of a joke, but nevertheless I’m very proud and amused at the same time :-). I guess I will have to change my blogging style in order to make it up in the future. So expect some more ‘publish some ideas quickly’ posts soon…

Here is something very interesting - I’ve discovered it some time ago when I was searching for general background information about convoys. This explains why it’s so hard to find anything theoretical and not directly from MS. More precisely, the ‘Processing convoy workflow scenarios’ patent has been linked to 8 different people, amongst them 1 very famous blogger named Lee.

 



I’ve seen numerous handy WMI scripts and code samples from fellow BizTalk bloggers and from the BizTalk help. Amazingly every one of these samples use late-bound objects calls to invoke methods and access properties from the BizTalk management objects. This makes the code rather verbose, it’s very inconvenient and also very error prone. There's a better way to write your WMI code. Therefore you have to download first and then install the 'Management (WMI) Extensions for Visual Studio .NET 2003 Server Explorer'. This tool makes WMI programming much easier and enjoyable (at least for me). It's no rocket science or anything but it comes in very handy for making your first steps on the WMI moon. You don’t have to take my word on it, look for yourself:
 
After having installed the extension you can go into your Visual Studio’s Server Explorer and select the namespace you want to add management classes from (select ‘add classes’ from the context menu).
 
 
After selecting the desired classes from your namespace (‘root \MicrosoftBizTalkServer’ I assume) the Server Explorer window will contain a list of the selected management object-types. It also shows a list of all instances for a given class when you click it. When having selected an instance, all of its properties will be shown inside the property-window (you could modify them from there too, but I wouldn’t recommend doing it this way).
 
 
Also methods can be invoked on classes and instances; this is nice for testing purposes. *No big deal* you are thinking of course; now pay attention:
 
When selecting 'Generate Managed Class' from the menu, the extension will automatically generate a wrapper class and add it to your solution’s startup project (it targets your .net project language).
 
 
The generated classes have strongly typed properties and methods, so you have access to and can invoke by simply using their name (even enum-types are created). You benefit from good old Intellisense again. Behind the covers the generated wrapper classes still use late-bound objects and calls of course, but you don’t have to care at least about this, nor write ugly late binding code. Now you can write clean high-level WMI code a lot faster.
Take a look at this little WMI sample (where I make a call to ‘GetInstances’: this overloaded method is created automatically and it requires only the where-part of the WQL query to return a typed collection of your WMI object-type).
 
 
Try to rewrite the following method (please don’t focus on the language change; it’s purely for educational purposes. I’ve never executed a single line of this code :-)
 
 
Into this:
 
 
Which one do you prefer?


A Biztalker's focus is primarily on the BizTalk SP1 release nowadays so I thought it might be useful to post about the arrival of the Enterprise library. Yep, it's finally out! For more information check MSDN.

 

Here are 2 fine bloggers that blog about the EL like we do on BTS:

Being Scott Densmore 

Tom Hollander's blog



The isolation setting is fixed and is SERIALIZABLE. So beware that even your most basic receive locations that only execute those very simple SQL statements such as 'select * from tablename' can generate locks. BTW, this is a general misconception: usually people think that select-statements never lock resources. Nothing is less true of course.
 
While having a shared lock on a range of keys, in addition to the keys themselves having locked, no records can be inserted. 
Here's a sample to demonstrate the effects of the SERIALIZABLE isolation setting:
 
Open your SQL Query analyzer
Open 2 seperate query windows to the local Pubs database
Copy & paste these samples statements:
 
Window A:
 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
Select * from authors where contract = 1
GO
 
Window B:
 
BEGIN TRAN
INSERT INTO [pubs].[dbo].[authors]([au_id],[au_lname], [au_fname],  [contract])
VALUES('666-66-6666','Grego', 'El', 1)
GO
 
Now, if you try to execute both queries you will see that the second query will always be blocked by the first, irrespective of the order. You can immediately unblock the process by typing, selecting and executing 'ROLLBACK TRAN' in the blocking transaction's window. Now repeat this test and replace 'SERIALIZABLE' with 'READ COMMITTED' and you will see that when you first start batch A, you can still execute Batch B simultaneously (which wasn't so with the SERIALIZABLE level).
 
Here are the isolationlevel-enumerator values from system.data:
 
[Flags]
public enum IsolationLevel
{
      // Fields
      Chaos = 0x10,
      ReadCommitted = 0x1000,
      ReadUncommitted = 0x100,
      RepeatableRead = 0x10000,
      Serializable = 0x100000,
      Unspecified = -1
}
 
The BizTalk SQL adapter always uses 0x100000. You can check this by viewing the requested locks in Enterprise Manager:
 
 
Now, I believe the above will rarely be a problem in real-life. You should only expect performance problems when you have a lot of transactions and a lot of simultaneous lock requests for the same heavy resource while having a bad database-design (having no or having the wrong indexes). You should also know that lock waits are perfectly normal: a simple wait for a lock is different from a deadlock. The waiting process will get the lock anyway when the process that's holding the lock completes.
If you use SERIALIZABLE my best advice is to tune you sql statements for performance (also having correct db-design, normalization, the right indexes,...) in order to make your select statement execute as fast as possible .
 
**UPDATED**
 
Is there a solution?
  • If you try to add the 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED' to a select-statement based receive location then you may have no issues at design time. But when you try to add a RL based on this SQL statement in the  BizTalk Explorer you will get a 'The SQL statement must be either a select or an exec' error.
  • You can add ‘With (Readcommitted)’ to the tables in the select, or data modification statement. 'Select * from authors with (Readcommitted) where contract = 1'. This will override the default Serializeable isolation level, and keep the number of locked records to a minimum. Credits go to Dirk Gubbels from Microsoft...
SQL Server locking experts' comments are very welcome...


I've just found out the hard way that GAC'ed publisher policy assemblies do not chain. When you have a policy.1.0, redirecting the binding of assembly v1.0.0.0 to assembly v1.1.0.0 and also having a policy.1.1, for redirecting the binding of assembly 1.1 to assembly 1.2, this doesn't result in a binding to the assembly 1.2 when your app requests 1.0 (but rather to 1.1). If you want this kind of binding-behavior I guess you will have to use publisher policy versioning.
 
Why do I tell all this? Well, I've never read anything about this before so I thought it would be nice to mention here.
I also want to thank Alan Shi, who confirmed and explained this binding behavior to me. For more excellent information regarding the GAC and Fusion you should definitely visit his blog here.


I’ve watched several times Jurgen Willis’ excellent online presentation about the Business Rule Engine (BRE). One of the BRE usage scenarios demoed by him contains a sample orchestration that uses the BRE to dynamically configure a delay time.
This confused me since it added another option to accomplish dynamic configuration of business processes. We are definitely facing a configuration dilemma now; here are some of the alternatives:
 
  • Config Files
    Use the default .NET config files as the store (BTSNTSvc.exe.config) for your key-value pairs or custom types. You can easily read the settings using the default .net classes from inside your orchestrations.
    This is definitely the easiest option. But it makes your business processes host-instance depended (every host instance can be differently configured). It’s also not easily deployable, when having different environments you will have to manually copy paste your configuration sections, you could easily make mistakes. I guess there are no tools available for the business users to manage the values.
 
  • Business Rule Engine
    Although I have the feeling the BRE and its terminology is not really geared towards this simple functionality (storing key-value pairs). Most of the BizTalk included samples use schema-facts, some of them use class-facts but none addresses the config management purpose which was demoed in the presentation.
    I’ve tested a couple of things myself, including calling the BRE from code inside an orchestration by using several Stringbuilder instances or a Hashtable as the argument(s). This seemed a very strange solution to me (it’s not easy to define the rules/vocabularies when having several instances of the same class).  Another option is to create a custom configuration class which gets and sets the values, this will simplify the vocabulary. Or you could always use the classic approach and create a custom schema to hold your configuration values.
 
 
Finally I emailed Jurgen, who appeared to be a very friendly and helpful man. He pointed me out that the BRE is in fact not specifically targeted at this scenario and that, in general, it focuses more on complex types than on using value types (especially when multiple instances are evaluated in the same policy). 


Let's go over some of the out-of-the-box options for executing a pipeline from inside your orchestration.
 
It struck my mind first that the MSMQT adapter IS in fact the messagebox.
 
  1. MSMQT
 
  • Set up a schedule with 1 MSMQT send port and 1 MSMQT receive port sharing the same MSMQT queue name (for example ' loopback' would make a lot of sense)
  • Create a correlation type and set based on the my MSMQT label property.
  • Assign the MSMQT message-label to a newly created GUID inside your orchestration.
 
Try to do a send and a receive and you will see that your pipelines will be executed. As a test I could successfully parse a message from inside a schedule.
 
Another very simple option is using the HTTP adapter, credits go 100% to Scott Colestock. Scott used this as just a temporary approach to get past this problem, and then switched to the loopback adapter below...
 
  1. HTTP
 
  • Use a solicit-response send port 
  • Use bogus HTTP page that simply echoes the content back.
 
<% @ webhandler language="C#" class="LoopbackHandler" %>
using System;
using System.Web;
using System.IO;
public class LoopbackHandler : IHttpHandler
{
   public bool IsReusable
   { get { return true; } }
  
   public void ProcessRequest(HttpContext context)
   {
      using(StreamReader sr = new StreamReader(context.Request.InputStream, true))
      {
         StreamWriter sw = new StreamWriter(context.Response.OutputStream, sr.CurrentEncoding );
         sw.Write(sr.ReadToEnd());
         sw.Flush();
         sw.Close();
      }
   }
}
 
This can be easily explained because it requires no knowledge of correlation types and correlation sets, since you are using request/response ports the whole way. If simplicity is the main goal then this solution is probably superior to the MSMQT one.
 
  1. Custom LOOPBACK Adapter.
 
I also had another idea. Why not make your own loopback adapter by writing a bogus solicit-response adapter that returns a response BizTalk IBaseMessage that is a copy of the original request message. Recreate the original individual message-parts and copy of the request stream to the response stream. It's very simple - download my sample loopback adapter here.
 
  • It's a custom coded VB.NET non-batched but non-blocking (async) adapter that really doesn't do anything.
  • Uses limited memory-footprint, streams to disk. 
  • To install use the MSI package. Don't forget to add the adapter by using BizTalk administration...
  • It auto generates the transmit location URI (in fact it's a GUID). I also added a Boolean property to specify whether you want the original message and part properties to be copied on to the response-message and parts.
 
Here are some of the benefits:
 
  • Trigger pipeline execution from inside your orchestration. Just define your outbound and inbound pipelines and they will be executed.
  • Send pipeline errors can be catched by adding a deliveryfailure-exception handler. Also adapter exceptions can be catched there, but since this adapter really doesn't do anything this will be very rare (at least I hope so).
  • Receive pipeline errors can be catched by adding a general SOAP-exception handler.
  • Execute mappings from inside your orchestration by defining a map on the inbound and outbound port. When you use the later, mapping failures will be catched by the SOAP-exception handler.
  • It's a black-hole adapter if you want. It can be used to ignore the processing of certain incoming messages. Make a send-port, name it 'VANISH' and subscribe to a given message-type or receive-port name for example.
  • It's very useful for doing in-order processing. You can for example receive messages from MSMQT through a pass-through pipeline (which is recommended BTW) and process messages in-order from start-to-end while doing exception-handled parsing/validation/mapping by implementing a serial convoy.
 
Here's a sample project that demonstrates some of the benefits.
 

Remarks:
 
  • The code can definitely be improved. It has been written very quickly in the scope of a POC. Alternatively you could make a better one using the adapter base classes and the wizard. In fact I'm hoping the community will see the benefit of this loopback adapter and someone else will make a better one. I'm not (yet, ha!) a streaming and multi-threading expert.
  • Apparently it is advised to return a read-only forwarding stream to the receive-pipeline. At least until SP1 arrives. I just used the VirtualStream class from the BizTalk Streaming assembly.
  • Do not forget, and as usual: there's no warranty at all. I haven't tested this very thoroughly yet so…use the adapter at your own risk.


You all probably know that MSMQ stands for 'Microsoft Message Queuing' and MSMQT is the acronym for describing the BizTalk MSMQ adapter. A quick reminder for those who already forgot: the "T" in MSMQT stands for transactional (not “Transport”)
 
Probably less common knowledge is what MSMQ acknowledgments (ACKs) are, so I have chosen this to be the topic for my first post. What are ACKS and in what flavors do they come?
 
Acknowledgments are system-generated confirmation messages that are sent to the administration queues specified by the sending application. When an application sends a message, it can request that Message Queuing return acknowledgment messages indicating the success or failure of the original message.
 
  • A reach acknowledgment tells you that the message reached its destination queue.
  • A receive acknowledgment basically tells you that some application successfully received a message from a queue.

Both acknowledgment types have positive (ACK) and negative (NACK) variants indicating - this is too straightforward - a success or a failure: positive arrival acknowledgments, positive read acknowledgments, negative arrival acknowledgments, and negative read acknowledgments.
 
If you want to get rapidly acquainted with acknowledgments you should definitely read this excellent article on MSDN: Reliable Messaging with MSMQ and .NET (Building Distributed Applications)
 
Personally having no prior experience with MSMQ acknowledgments, I started my first tests having big expectations. I built a .NET application and sent my 1st MSMQ message with an ACK-level set to full_reach and full_receive using a non-transactional admin queue. (my machine is a simple MSMQ independent client so I send to other machines using outgoing queues). Also not wanting to be too haughty I targeted my first message send at a regular MSMQ server. As expected my message arrived quickly at its destination queue where I subsequently could read the message through code.
 
Wonderful, I had 2 ACKs in my sending machine's admin queue:
 
ACK1 MSMQ message class = The message reached the queue.
ACK2 MSMQ message class = The message reached the queue.

Since this first test being a big success I already wondered what would happen if I'd send the same message again, but now targeted to the BizTalk MSMQT adapter.
 
I quickly set up a BizTalk MSMQT receive location with a passthru pipeline and a file send port subscribing to the MSMQT port. After BizTalk created the flat output message I was really surprised - even a bit disappointed at the same time - because I only found 1 acknowledgment in my admin queue:
 
ACK1 MSMQ message class = The message reached the queue.

Where the heck did the receive ack go? Did I make a mistake? I did have a valid subscription and it was consumed correctly because I had a file. After doing some research, newsgroup postings and e-mailing, a very helpful person from MS gave me the answer: 'For Biztalk, multiple "applications" can receive the message and MSMQT doesn't know how many got it, so it was decided that receive ACKs would only confuse the customers.'
 
Slowly getting over my depression I started focusing on the ACK I did receive. I started to think about the opportunities this ACK creates: you now have a level of traceability at the sender's side. For my next test I sent a message to an invalid MSMQT queue - more precisely I used an invalid name being a non existing queue on MSMQT. Admin queue:
 
NACK1 MSMQ message class = The destination queue does not exist
 
  • Event viewer: Destination queue 'wrong queue' cannot be reached. For local BizTalk queues, the receive location may not exist or may be disabled.
  • HAT: Nothing
 
Exactly what I expected! This reminded me of some interesting must-read posts on this subject by Darren Jefford's blog titled MSMQT, Transactional Queues and Xml Validating Pipelines and MSMQT: Debugging and Getting hold of malformed messages.
 
Conclusion: if the sending of a message fails the sender receives a NACK message in the admin queue and eventually after exhaustion of the retries MSMQ places the bad message from the outgoing queue in the dead-letter queue (optional: see below for more information). Darren Jefford advices to always use passthru pipelines for MSMQT receive locations. Now let's ignore his advice and try the opposite. What would happen if I would send a message to an existing queue but an exception is raised from inside the receive pipeline?
 
I quickly configured my MSMQT receive location to use a pipeline implementing the flat file parse (FFDASM) component. Next I intentionally sent a malformed FF message to the MSMQT queue - generating a parsing error. Here is what I got in my admin queue:
 
NACK1 MSMQ message class = The destination queue does not exist

I expected to have a more meaningful description as for example 'Parsing failed', but I received the same - now totally irrelevant - description. As a consequence the message sender cannot see the difference between these 2 different types of errors. I asked my MS contact again and he gave me this explanation: 'because we cannot define new values for MSMQMessage.Class, we were pretty much stuck with the existing ones.' This means, I think, that they were stuck with the standard MSMQ API error enumerators.
 
So here's my conclusion: If you send messages to MSQMT receive locations you should always choose between
 
(A) Use a passthru pipeline on the receive location or
 
(B) Use a custom pipeline but specify a dead-letter queue for the message and/or implement acknowledgments/logic to handle failed messages due to pipeline execution errors.
 
As for the sake of completeness I also want to mention that MSMQT also sends positive ACKS for each successful message receival. This assures us that your message was handled fine and survived pipeline execution without any error.
 
Now having all these extra bits of information regarding ACKS I'd like to finish by issuing a little warning. An example of a bad design would be to create some kind of service that sends messages 1 by 1 to a MSMQT node - while waiting in between each send for an acknowledgment. This would probably work from a functionality point of view but never from a performance perspective. Read this: 'Using the Right Tool for the Right Job' chapter
 
To finish my article I'd like to comment on the overall very fine transcript of the Microsoft Support WebCast - BizTalk Message Queuing in Microsoft BizTalk Server 2004 where Rajan Dwivedi states 'As far as interaction between MSMQT and MSMQ is concerned, MSMQT can receive messages from MSMQ, and it can also send messages to MSMQ without any difference.' Well Rajan, I'm not so sure ;-)


The MSBTS_ServiceInstanceSuspendedEvent WMI event is fired by the BizTalk Engine whenever a "message" is suspended. This happens (amongst other reasons) when all send retries fail (for example when a connected system is down) or whenever exceptions occur during the pipeline execution (for example when message validation fails).
 
For this little article I'd like to focus on the first category: outbound suspended messages caused by systems being temporarily unavailable. Usually admins like to receive notifications whenever one of their systems goes off-line. You can set up a NT service that consumes BizTalk MSBTS_ServiceInstanceSuspendedEvents and notifies the admins for example by e-mail (to the Biztalk admin and/or appropriate system admin). They can then fix the problem and bring their failed system back up.
 
Now the problem is that you still have to deal with those suspended messages that sit in the message box as a result of the failure. They simply have to be resubmitted and this can be done using the HAT tool. This can be a quite repetitive task that's very prone to errors (try resending the wrong message). In many cases an automatic solution would make a better one. Let's see what can be done:
 
One could react by upping the retry count to its maximum value? Ok, this would automate things a lot but has 1 very big disadvantage: you lose your notifications because the message will never suspend :-( Who will bring the system back online? You NEED these notifications so this isn't a viable solution: you have to lower the retry count back to an acceptable level. Is there another solution? Yes there is: add your own custom WMI events to BizTalk Server!
 
What if we could add extra custom events that create the functionality to receive notifications upon the retry itself - without requiring a message to be suspended? This sounds very complicated but is in fact a very easy task when you use the Microsoft Enterprise instrumentation Framework to create a custom event class.
 
For those that never heard of it, this is what EIF can do for you! From the EIF README:
 
'The Microsoft Enterprise Instrumentation Framework (EIF) enables you to instrument .NET applications to provide better manageability in a production environment. EIF is the recommended approach for instrumenting .NET applications. It provides a unified API for instrumentation that uses the existing eventing, logging, and tracing mechanisms built into the Microsoft Windows® operating system, such as Windows Event Log, Windows Trace Log, and Windows Management Instrumentation (WMI). Members of an operations team can use existing monitoring tools to diagnose application health, faults, and other conditions.
 
An application instrumented with EIF can provide extensive information such as errors, warnings, audits, diagnostic events, and business-specific events.'
 
The EIF also forms the basis/prerequisite for the Microsoft .NET Logging Application Block. This block represents the 'new' way to do logging /exception management - replacing the older EMAB (exception management application block).
 
Let us - by means of example - add the following events to our BizTalk Server 'event source':
 
  • TransportLostEvent: a system goes down for the 1st time = First failure
  • TransportRecoveredEvent: a system comes back up again = A retry succeeds
 
I have used very basic sample classes for these events. Feel free to e-mail me to get the sample - I haven't got uploads working yet :-(
 
The context of the message will provide us with our basic building blocks and determine when these events have to be triggered. The 'http://schemas.microsoft.com/BizTalk/2003/system-properties' namespace contains 3 unpromoted properties named ActualRetryCount, RetryCount and RetryInterval.
 
  • RetryInterval is a static value representing the value set on the Send Port.
  • RetryCount - on the other hand is - very confusing - not a static value but represents the number of retries still available - and is lowered by 1, by the Engine for each failed transmission attempt.
  • ActualRetryCount, which BTW returns no results when you look for it in the help, is also a dynamic value that is incremented by 1 for each transmission attempt.
 
So how can we make this all fit together, wherefrom can we trigger our events? There are 2 scenarios possible: a custom adapter and a custom pipeline component (for integrating with existing adapters).
 
Here's a sample piece for a custom adapter:
 
'If message transmission succeeded
oProperty = msg.OriginalMessage.Context.Read("ActualRetryCount","http://schemas.microsoft.com/BizTalk/2003/system-properties")
If Not oProperty Is Nothing Then
'A previously failed send operation has now succeeded actualretrycount>0 and msg.TransmitSuccesfull is true)
If System.Convert.ToInt32(oProperty) > 0 Then
myTransportRecovered = New TransportRecoveredEvent
obj = msg.OriginalMessage.Context.Read(InterchangeIDProperty.Name.Name, InterchangeIDProperty.Name.Namespace)
If Not IsNothing(obj) Then myTransportRecovered.InterchangeId = System.Convert.ToString(obj)
'Continue to build and finally raise the event
.
myEventSource.Raise(myTransportRecovered)
Else
'If message transmission failed
'If actualretrycount is 0 then this means that system failed for the 1st time: raise TransportDownEvent
oProperty = msg.OriginalMessage.Context.Read("ActualRetryCount", RetryIntervalProperty.Name.Namespace)
If Not oProperty Is Nothing Then
If System.Convert.ToInt32(oProperty) = 0 Then
myTransportLost = New TransportLostEvent
and so on...
myEventSource.Raise(myTransportLost)
.
A very nice idea would be to develop an "EIF enhanced" version of the adapter base classes that trigger additional events. Anyone interested?
 
I've also succeeded into making a sample pipeline component that raises the TransportLostEvent from inside a pipeline - creating the opportunity to integrate this functionality with existing adapters. I tested this very rapidly/effectively thanks to the pipeline component wizard by Martijn Hoogendoorn...
The downside for pipelines is that - if I'm correct - we have no notion of the current transmission attempt result from inside (the result) so we cannot raise the TransportRecoveredEvent. What we do have, is the result of the previous attempt and the actualretrycount - creating the possibility to trigger the TransportLostEvent upon the first message retry.
 
As a final note always remember that WMI events do have a performance impact. So you may want to just send them to the WTE (trace events) sink if you don't need them and performance is an issue. The nice thing about the EIF is that this can be done dynamically and doesn't require a restart of the 'Event Source' or changing the pipeline. See the configuration section in the readme of the EIF for more info.
 
Here are some stats for the curious - Event sink Average events per second:
 
  • Windows Event Log 220
  • MSMQ 120
  • WMI 520
  • SQL Server Basic Log 300
  • SQL Server Flexible Log 70
  • EMAB with the Windows Event Log 120
     


Do you remember those good old BizTalk 2002 days when you only had to make a couple of clicks through the BizTalk messaging manager to refresh a mapping? Well it's time to share with you a nice technique that makes BizTalk 2004 mapping updates just as easy to make and deploy:
 
  • For this technique to work you have to make sure you always compile and distribute your mappings into a 'mapping only' assembly - this will simplify things a lot. Do not put your referenced schemas inside this mapping assembly.
 
  • Keep always track of the version-number your mapping assembly has (by setting the version number in the assembly config file.). Remember that version numbers are in the format "Major.Minor.Build.Revision".
 
  • Deploy your finished solution into your production environment. This can be done in a variety of ways: using an msi or you could just deploy assemblies manually using the deployment wizard. Usually you make this decision depending on the complexity of your solution.
 
  • Now you discover a mapping error requiring an update after everything is already deployed. You are afraid to touch the installed assemblies - you know how complicated things can get when undeploy redploy. You don't want to break any dependencies or anything...but it's not a breaking change - just a fix - changing a couple of mapping links...
 
  • The solution: Just recompile your updated mappings project and up the version number and deploy your updated assembly using the deployment wizard while leaving your old assembly in place. You can deploy your new assembly to the GAC and optionally - not mandotary - also into BizTalk. This makes then a total of 2 versions of your mapping assembly deployed side-by-side into Biztalk at the same time (the original and the updated one). This doesn’t affect your running solution at all, because BizTalk references mappings strongly, it will still keep using the original assembly from the GAC.
 
  • Now change the .NET assembly binding behavior by inserting a binding redirection into the XML config file.
    You can do binding redirections on both application level (BTSNtsvc.exe.config in our case) and on machine level by updating the machine.config file. You can update config files manually or use the .NET configuration framework mmc snap-in that we will use for simplicity sake. Here's a sample binding redirecting from my machine.config file:
 
  •   <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="StoraEnso.Mappings.Fenix" publicKeyToken="15b134fbf6ea6bf5" />
            <bindingRedirect oldVersion="1.0.0.0" newVersion="1.1.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
 
  • Recycle (restart) the BizTalk host instances - to recycle the app domains that use the mapping assembly. Voila: BizTalk is now using the new version!
 
  • Not happy with the result? Manually remove the binding redirection again or using the snap in, recycle the hosts and you are back to the old version, it's just that easy!
 
For the curious: I've also tested BizTalk assembly redirections using a publisher policy assembly and it seems to work fine. Remember to up the Major or Minor part of the version for this to work. You now have the capability to create an msi that installs/uninstalls an updated mapping assembly.
 
Additionally I'd also like to mention that binding redirections can be used for BizTalk schema assemblies too. This, though, creates extra complications because BizTalk will always match duplicate assemblies to a given message type if you have 2 versions deployed into BizTalk. As a consequence you will have to make all your receives/pipelines what I call 'Strongly Typed' and this indicates extra property promotion work (the type) and I had to play with SchemaWithNone in my code to make FFDASM and other pipeline components work correctly...
 
So I guess - never tested this myself - it's better to only GAC updated schema assemblies - if you'd want to use this technique at all for schema assemblies....
 
A final word of advice: technically it's possible to keep on patching forever and ever - though this would make a very bad practice ;-)


This simulates an orchestration callrules action from code:
 
MyArrayList = new System.Collections.ArrayList();
MyPolicy = new Microsoft.RuleEngine.Policy(YourPolicyName);
MyTracer = new Microsoft.RuleEngine.DebugTrackingInterceptor();
 
You will have to create your facts in here. Use TypedXmlDocuments or custom objects (see the BizTalk help for samples)
 
MyArrayList.Add(MyFact1);
MyArrayList.Add(MyFact2);
MyPolicy.Execute(MyArrayList.ToArray(),MyTracer);
MyPolicy.Dispose();
System.Diagnostics.Trace.WriteLine(MyTracer.GetTraceOutput());
 
The above line will redirect the traces to the windows event trace.
Use the excellent debugview utility from sysinternals to view the traces.


Here's a presentation containing an overview of the flat file parser annotations that can be manually inserted into the BizTalk message schema. This is part of a presentation I gave at the Belgian BTS user group meeting a couple of weeks ago. There is also a sample project containing different schemas per annotation showing each annotation's purpose. My main source of information was the BizTalk newsgroups where David Downing makes the beautiful weather for this topic. Just for the record: as usual everything is 'AS IS', so there's no warranty at all...
 
BTW this is my first post using the Simple Blog Editor InfoPath form that I found thanks to Capo