News

My Stats

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

Twitter










Recent Comments


Recent Posts


Archives


Post Categories


May 2009 Entries

BAM Portal Related Document Links That Actually Work


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.

posted @ Thursday, May 28, 2009 3:02 PM | Feedback (5) | Filed Under [ BizTalk - EAI - B2B ]


Custom StreamReader with FSM


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.

posted @ Monday, May 25, 2009 9:55 AM | Feedback (0) | Filed Under [ BizTalk - EAI - B2B ]