Geeks With Blogs
El Grego BizTalk blog
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. Posted on Tuesday, June 23, 2009 10:31 AM BizTalk - EAI - B2B | Back to top

Comments on this post: BAM Typed API alternative

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

Copyright © Gregory Van de Wiele | Powered by: