Geeks With Blogs
El Grego BizTalk blog

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.

Posted on Tuesday, February 24, 2009 11:26 AM BizTalk - EAI - B2B | Back to top


Comments on this post: Some thoughts on Service Location (SL) and Dependency Injection (DI) with BizTalk...

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Gregory Van de Wiele | Powered by: GeeksWithBlogs.net