Yossi Dahan [BizTalk]

Google
 

Monday, August 11, 2008

Zombies

A lot has been written about Zombies in BizTalk, but somehow they never really caused me too much problem. until today.

In one of our processes we are calling a web service to perform a certain lookup.

That web service’s implementation (whether correct or not) is to return the instance of the class if found or null otherwise.

When the service returns a null BizTalk receives an empty message, which triggers an exception in the process -

Microsoft.XLANGs.Core.MissingPartException: The XLANG/s message has no part at index '0'.  The total number of parts found in the message is '0'. If you expect a multipart message, check that the pipeline supports multipart messages such as MIME.

I’m quite all right with that, BizTalk is definitely correct – we have returned an empty stream as a message which means nothing.

And so - we've added an exception handler around the call to the service and our orchestration’s flow carries on correctly all the way to the end shape. as expected.

However, contrary to the expected at this point the orchestration instance gets suspended by BizTalk with the error - “The instance completed without consuming all of its messages. The instance and its unconsumed messages have been suspended.”

I believe this behaviour has been introduced in BizTalk 2006 - 2004 was quite “happy” to have the so called "zombies" in the process, and it was up to the developer to handle those (or not, as the case often was); since 2006 this had become an error and if a process ends with unconsumed messages the process gets suspended and the unconsumed messages are available for inspection.

Generally, I think that making a zombie an explicit error is a good idea, although it would have been nice to be able to set whether this behaviour is required on a per-process basis, however - in our case we found this very problematic - we were in a position where we couldn't consume the message properly (due to the exception handler) but although we have handled the exception we ended up with a suspended in stance as it appeared as a zombie. we could not win.

I have opened a support call on this one, waiting to hear if the product group agrees that this is incorrect behaviour or not (I seem to be getting conflicting thoughts). I'll try to keep this post updated when I get an answer.

(You can read more details about this here  - http://technet.microsoft.com/en-us/library/bb203853.aspx and http://blogs.msdn.com/biztalk_core_engine/archive/2004/06/30/169430.aspx

An interesting point is that this case is not listed in the list of causes for zombies in these articles, which makes me wonder – should an exception raised through a receive shape, which was properly handled by an exception handling result in a zombie?)

Labels: , , ,

Sunday, July 20, 2008

Which System Exception?

I'm almost embarrassed to post this one, but it send me chasing windmills for a couple of hours, so if I can save that from any other unfortunate person it served a purpose I guess -

I have a call from one orchestration to another.

In the calling orchestration I wanted  to catch any exception that would occur on the called orchestration (or anywhere else down the line) and so I swiftly wrapped the call in a non-transactional scope and added an exception handler.

Being the keyboard-fan that I am (BizTalk is completely unfriendly to us keyboard types, but still...) when the type selector opened I did what I always do - I types the name of the class I wanted (System.Exception) and pressed enter.

The problem was that I did not type the class name ('Exception') but the full name ('System.Exception') and that got me System.SystemException class as the selected type, only that I did not realise that at the time.  apparently the type selector ignores special characters being keyed in?!

It was much later that I realised exceptions that were thrown in my called orchestration were not being caught in the calling one and even then it took me a good couple of hours to realise what was the reason (I simply did not look carefully enough at the exception type - System.SystemException just looks like System.Exception when you (well - I) glance at it!

Three take ways for me -

  1. Pay more attention when doing even the most trivial tasks. (trivial, isn't it?)
  2. Consider being less zealous about using the keyboard when doing BizTalk development
  3. But seriously - consider always having a general exception handler to catch whatever exceptions were not caught by other handlers. I should have been mostly covered by catching System.Exception (although BizTalk, unlike C# or VB.net does support exceptions that do not inherit from System.Exception, see Charles Young post on the subject), but this could have helped at least identify the problem.

Labels: , ,

Wednesday, December 12, 2007

Exception, Orchestration, Serialisation.

I was adding a custom exception yesterday to a helper class I’m calling from an orchestration.

Usually, my exception handlers in the orchestration are quite short; this time, however, I wanted to do a bit more, which included calling a web service when a particular expcetion is caught.

While implementing this I learnt something interesting (which, arguably, I should have known a long time ago – just to show how difficult it is to catch up on all the changes in the .net framework) -

In.net framework 2.0 a Data property of type IDictionary was added to the Exception class, which by it's own is not a problem, only that IDictionary is not serialisable and so could have proved rather difficult to anyone using Exception, especially in a BizTlak environment.

Luckily (but not surprisingly) the .net framework team have implemented ISerializable in the Exception class, which helps, but does cause a small headake to the unexpecting BizTalk developer (me).

But first - I have to apologise - again I'm not familiar with all the details around this, and am resorting to pure guesses of a couple of points (will be happy to get more information if you care to enlighten me), still - I'm sure this will be useful to most people...

When you mark a class as [Serializable], as the runtime deserialises a class it attempts to call a parameterless constructor to create an instance of the type; the serialiser will then populates all the members of the class through their public properties (I suspect that this is, partly at least, why Xml Serialisation serialises public members only).

When working with ISerializable, however, the runtime expects a constructor that takes SerializationInfo and StreamingContext as parameters; it is expected that the constructor will populate the members out of the SerializationInfo collection.

I believe that the runtime interrogates the type to be deserialised and, once it finds that the type or any type in its inheritance path implements ISerializable it takes the second approach mentioned.

Not realising the Exception class implements ISerializable ,I did not have the expected constructor in my class, which meant that when BizTalk tried to deserialise the object (between the send shape calling the web service and the receive shape expecting the response) it failed, which now exaplains the error reported in the event log -

The constructor to deserialize an object of type ‘[custom exception class name here]’ was not found.


Adding the constructor with the two parameters to my custom exception class allowed it to pass the deserialisation with no errors; however – I was now facing a second problem – after indicating that my class implements ISerializable and addin the constructor required the members of the Exception class, from which my class inherited, including the Data member now deserialised correctly; my own class' member,however, did not.

There are two ways to overcome this - I could have simply mapped my properties (after all I only had a couple of strings to keep with the exception) to the Exception's Data property (have the getter and setter of each property use the collection internally, and so all the data will be capture in the Exception base class and so serialised with it, or - I could implement ISerializable fully which really only means

1. Firstly - adding my members to the serializationInfo member of GetObjectData:

public override void GetObjectData(SerializationInfo si, StreamingContext
context)
{
base.GetObjectData(si, context);
si.AddValue("member1Name", member1Value);
si.AddValue("member2Name", member2Value);
}

2. Secondly - populating the members back in the constructor:

protected MyCustomException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
member1Name= info.GetString("member1Value");
member2Name= info.GetString("member2Value");
}


Voila! it all serialises and deserialises ok now. if only I didn't have to spend a whole day to figure this out!

Labels: , ,

Thursday, September 27, 2007

Problem due to an overload with a generic type

Here's another interesting one -

Imagine a class that looks something like this -



public class MyClass
{
public static void test(string a, string b)
{
}
public static void test(int a, string b)
{
}
}



From an expression shape in BizTalk you can now use

MyClass.test("string","string");
or

MyClass.test(1,"string");

and everything compiles just fine.

but add the following overload to your class -
        public static void test(string a, IDictionary c)
{
}
and now try to use the first overload from an expression shape (which worked just fine before) -

MyClass.test("string","string");

and you will get - "unknown system exception" with no file name or line number to help in sight.

I know BizTalk does not support generics, but I did not think having generics in the another method, one I'm not calling from BizTalk, would be a problem; and in fact - change the call in the expression shape to the overload that takes the int first -
MyClass.test(1,"string")
and it would compile just fine.

From this I can only gather that this has something to do with how .net resolves the overload to to use - in the error case, it looks at the first parameter passed in and identifies it as a string, so both the [string,string] and the [string,IDictionary] overloads fit, which means it needs to evaluate the second parameter, and, presumably, this is where it "blows up";
By changing the first parameter passed in to be an int, the compiler does not need to look into the overload that uses IDictionary as all and so it compiles ok.

And indeed, as soon as I add one this overload to the class -

public static void test(int a, IDictionary c)
{
}
I get an "unknown system exception" when calling using int as the first parameter.

Labels: , ,

Wednesday, August 29, 2007

<xsl:message>

How could I not know about this? I guess I simply did not expect it to exist, but now that I know it does I can easily justify it, especially as it is so useful!

And just in case anyone else missed it -

<xsl:message>some text here</xsl:message> will output "some text here" to the console, which is nice but not so useful.

<xsl:message terminate="yes">some text here</xsl:message>, on the other hand, will raise an expcetion with "some text here" as the message, which, unless handled, will cause the orchestration to get suspended and "some text here" written to the event log as part of the error, something like this:

Uncaught exception (see the 'inner exception' below) has suspended an instance of service '********************'.
The service instance will remain suspended until administratively resumed or terminated.
If resumed the instance will continue from its last persisted state and may re-throw the same unexpected exception.
InstanceId: 4c40dfad-d915-4691-a01e-d2df4393acb1
Shape name: Construct Response set
ShapeId: 5ed349ae-4a14-479f-8f84-6eaebd955de0
Exception thrown from: segment 5, progress 37
Inner exception: Transform terminated: 'some text here.'.

Labels: , ,