Wednesday, December 30, 2009

Biztalk ESB Toolkit 2.0: Exception Management Gotchas - Create the Fault Message in the right place

I've been having a lot of fun lately with the ESB Toolkit. It's got lots of great features. One of my favorites is the Exception Management piece which is very easy to use and surpasses just about every EM framework that's already out there.

However, one small issue I've encountered is that when using the Exception Management framework, you must only create your fault message inside an Exception handler in your orchestration.

Code such as this:

FaultMsg = Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.CreateFaultMessage();

Anywhere besides inside an exception handler will cause your CPU to peg out and your orchestration to hang indefinitely. On one occasion, I've seen the process complete, but that was when I started it on a Friday afternoon and left for the weekend to find it complete on Monday morning. Other times, I've had to terminate the orchestration and then restart the host instance to clear it out and return my CPU to a less-stressed state.

The reason this happens is because, when creating the fault message, ESB sets a number of properties for you, some of which are retrieved from the instance of the System.Exception class that is accessible from within the Exception block.

I solved this issue by instantiating my own exception object and throwing it when I hit a state in my orchestration that meant we shouldn't go on anymore. If you want to send a fault message and just keep on going, though, as far as I can tell you're out of luck.

One other caveat--your own exception must be an instance of the System.Exception class. If you use your own custom exception, even if you inherit from System.Exception, ESB will throw an error similar to the one below when you submit it.

Error 115004: An unexpected error occurred while attempting to retrieve the System.Exception object from the ESB Fault Message.

So, unfortunately, you can't use custom exception types and work with the Exception Management Framework.

Thursday, December 3, 2009

Endlessly Looping Rules - After Effects

I can't speak for the entire world here, but this has happened to me more than once: when execution of a rule in the BRE hits an endless loop and memory and processor resources slowly get chewed up you may find that you'll have to do more than just kill off the offending BizTalk artifacts.

After everything manages to return to some state of normalcy, you may find that the BizTalkMgmtDb database and the BizTalkRuleEngineDb database are unavailable. When attempting to access, you get the standard unavailability-related message: "Cannot open database "BizTalkMgmtDb" requested by the login. The login failed." Your login is probably fine. The DB is just offline, but SQL Server doesn't seem to know it. Further attempts to look at it in SQL Server Management studio may yield a slightly different message regarding the inability to connect because of memory issues (which is probably because of the endless loop).

For me it was a simple solution. Just take the database offline and bring it back by right-clicking each of the aforementioned databases names in the SQL Server Management studio and select Tasks|Take Offline. Then bring it back online by selecting Tasks|Bring Online. That should clear the memory and get you up-and-running.

And double-check your rules to avoid endless loops.

Tuesday, December 1, 2009

XmlDocument Serialization in BizTalk 2009 (NOT!!!)

For those who are not already in the know on this, the System.Xml.XmlDocument object that we all know and love is, ironically, not serializable. Certainly a mistake or misunderstanding somewhere from Microsoft land, but as of version 3.5 of .NET, it's still missing this capability. You would think...

Anyway, this one has really bitten me in the rear in BizTalk as BizTalk serializes darn near everything. Where this became a problem has been in the creation of .NET components that are called from orchestration.

If you choose to use a class that has an XmlDocument object as one of its members, you'll find the message "Type 'System.Xml.XmlDocument' in Assembly 'System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable." This occurs anytime that BTS attempts to serialize a class that uses an XmlDocument as an instance member. Oddly enough, this won't apply to variables that are of the XmlDocument type in the orchestration as BTS knows it's not serializable and won't try.

There are a few ways around this dilemma:
1. Mark the member as NonSerializable. BTS will not attempt to serialize the object and you shouldn't see this error.
2. Create all methods that return XmlDocument types as static members. No instance == no persistence == no serialization.
3. Return XmlNodes instead. An XmlDocument can easily be converted to an XmlNode object which is serializable.
4. Build all your XmlDocuments from within the orchestration in Expression Shapes. It's ugly, but shouldn't cause you problems.
5. Make sure there are no persistence points in your orchestration. [Sarcastically] Yeah, right... Good luck with that ;-)

Oh, and don't forget to GAC your components and restart your Host Instances...