Monday, September 26, 2005 #

About compatibility…

The BizTalk 2006 version and API is 100% backwards compatible with the 2004 version and API. BizTalk 2006 is built against .NET2.0 while the BizTalk 2004 assemblies were built against .NET1.1. Although I’m not working for Microsoft this surely means that for the BizTalk 2006 version the Microsoft BizTalk product team has:
 
1. Checked the re-used BizTalk 2004 code parts against the new .NET version for incompatibilities and resolved all of them for the BizTalk 2006 release
.

2. Rewritten parts of the original BizTalk 2004 implementation in order to benefit from the new framework version (such as a performance gain) without breaking compatibility with the previous BizTalk version.

3. Added a lot of new BizTalk functionality written from scratch in .NET2.0 code.

In general .NET framework supports installing and running different framework versions side-by-side on a single machine. By default your custom old .NET1.1 applications will run with .NET2.0 when you run them on a machine with 2.0 installed. If you detect incompatibilities you can instruct .NET to load the old runtime version you originally built your application against (by means of configuration). Or you can choose to fix the incompatibility in your code and recompile for .NET2.0.

Whole different story for your newly written .NET2.0 applications: they only run with 2.0 or higher compatible version (for example 2.1). 

Microsoft BizTalk 2006 is a ‘new application’ and is ‘built against’ .NET 2.0 (beta) and as a consequence will only run with .NET framework 2.0 or higher compatible version. The BizTalk 2006 host instances will load and execute code using CLR .NET2.0 and as a consequence the assemblies it loads will execute within .NET 2.0. Your assemblies used inside orchestrations, your custom adapters and your pipeline components and their dependencies will all have to be compatible with .NET2.0. You don’t have the option to instruct to load the .NET framework version you built your assembly against because loading 2 different CLR versions in the same process is not supported. Here is a good post from Junfeng Zhang about the subject: The CLR Side by Side and Compatibility.

This means that as a BizTalk developer you should at least perform step 1 from the above steps for all your BizTalk 2004 custom code. If you’re lucky you detect no incompatibilities and it will work by default. But if you do detect incompatibilities then you’ll have to re-code and re-compile. For more information on the .NET CLR see Suzanne Cook’s weblog

posted @ Monday, September 26, 2005 9:53 AM | Feedback (1)

Friday, September 23, 2005 #

BizTalk 2006 SDK: new BaseAdapter

The SDK of BizTalk 2006 Beta2 will include a new version of the adapter base classes. These will not be backwards compatible with the original BizTalk 2004 SDK classes.

The API has changed and the internals have changed (uses System.Transactions for example). Adapters that have been originally built with the 2004 adapter base classes should continue to use and be deployed with this version.The .NET1.1 compiled assembly of the old base classes should by default work with.NET2.0 CLR.

You could of course prefer to re-compile for .NET2.0 but you will get some warnings during compilation time.

posted @ Friday, September 23, 2005 6:40 AM | Feedback (0)

Wednesday, April 06, 2005 #

Some great news...

Although I'm still recovering from an earlier *shock* (from when I received the totally awesome MVD award), I'm proud to announce that as of this month I'm a genuine, fully-fledged Microsoft MVP for BizTalk Server. This is really fantastic!

posted @ Wednesday, April 06, 2005 5:08 PM | Feedback (3)

Monday, March 21, 2005 #

‘Processing convoy workflow scenarios’ patent

For those who are wondering why I’m not blogging very regularly: It’s not that I’m lying on my back and sun-bathing on the beach or anything (which was never been an option since it has been snowing a lot), I'm just rather busy lately. I was doing a SP1 evaluation earlier, for which MS has granted me a prestigious award for ‘Most Valuable Debugger’. It’s a kind of a joke, but nevertheless I’m very proud and amused at the same time :-). I guess I will have to change my blogging style in order to make it up in the future. So expect some more ‘publish some ideas quickly’ posts soon…

Here is something very interesting - I’ve discovered it some time ago when I was searching for general background information about convoys. This explains why it’s so hard to find anything theoretical and not directly from MS. More precisely, the ‘Processing convoy workflow scenarios’ patent has been linked to 8 different people, amongst them 1 very famous blogger named Lee.

 

posted @ Monday, March 21, 2005 9:06 AM | Feedback (0)

Wednesday, March 16, 2005 #

BizTalk WMI programming: How to write cleaner WMI code a lot faster

I’ve seen numerous handy WMI scripts and code samples from fellow BizTalk bloggers and from the BizTalk help. Amazingly every one of these samples use late-bound objects calls to invoke methods and access properties from the BizTalk management objects. This makes the code rather verbose, it’s very inconvenient and also very error prone. There's a better way to write your WMI code. Therefore you have to download first and then install the 'Management (WMI) Extensions for Visual Studio .NET 2003 Server Explorer'. This tool makes WMI programming much easier and enjoyable (at least for me). It's no rocket science or anything but it comes in very handy for making your first steps on the WMI moon. You don’t have to take my word on it, look for yourself:
 
After having installed the extension you can go into your Visual Studio’s Server Explorer and select the namespace you want to add management classes from (select ‘add classes’ from the context menu).
 
 
After selecting the desired classes from your namespace (‘root \MicrosoftBizTalkServer’ I assume) the Server Explorer window will contain a list of the selected management object-types. It also shows a list of all instances for a given class when you click it. When having selected an instance, all of its properties will be shown inside the property-window (you could modify them from there too, but I wouldn’t recommend doing it this way).
 
 
Also methods can be invoked on classes and instances; this is nice for testing purposes. *No big deal* you are thinking of course; now pay attention:
 
When selecting 'Generate Managed Class' from the menu, the extension will automatically generate a wrapper class and add it to your solution’s startup project (it targets your .net project language).
 
 
The generated classes have strongly typed properties and methods, so you have access to and can invoke by simply using their name (even enum-types are created). You benefit from good old Intellisense again. Behind the covers the generated wrapper classes still use late-bound objects and calls of course, but you don’t have to care at least about this, nor write ugly late binding code. Now you can write clean high-level WMI code a lot faster.
Take a look at this little WMI sample (where I make a call to ‘GetInstances’: this overloaded method is created automatically and it requires only the where-part of the WQL query to return a typed collection of your WMI object-type).
 
 
Try to rewrite the following method (please don’t focus on the language change; it’s purely for educational purposes. I’ve never executed a single line of this code :-)
 
 
Into this:
 
 
Which one do you prefer?

posted @ Wednesday, March 16, 2005 6:00 AM | Feedback (24)

Tuesday, February 01, 2005 #

Enterprise Library is -also- there...

A Biztalker's focus is primarily on the BizTalk SP1 release nowadays so I thought it might be useful to post about the arrival of the Enterprise library. Yep, it's finally out! For more information check MSDN.

 

Here are 2 fine bloggers that blog about the EL like we do on BTS:

Being Scott Densmore 

Tom Hollander's blog

posted @ Tuesday, February 01, 2005 9:00 AM | Feedback (8)

Thursday, November 25, 2004 #

The BizTalk SQL Server Adapter isolation level

The isolation setting is fixed and is SERIALIZABLE. So beware that even your most basic receive locations that only execute those very simple SQL statements such as 'select * from tablename' can generate locks. BTW, this is a general misconception: usually people think that select-statements never lock resources. Nothing is less true of course.
 
While having a shared lock on a range of keys, in addition to the keys themselves having locked, no records can be inserted. 
Here's a sample to demonstrate the effects of the SERIALIZABLE isolation setting:
 
Open your SQL Query analyzer
Open 2 seperate query windows to the local Pubs database
Copy & paste these samples statements:
 
Window A:
 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
Select * from authors where contract = 1
GO
 
Window B:
 
BEGIN TRAN
INSERT INTO [pubs].[dbo].[authors]([au_id],[au_lname], [au_fname],  [contract])
VALUES('666-66-6666','Grego', 'El', 1)
GO
 
Now, if you try to execute both queries you will see that the second query will always be blocked by the first, irrespective of the order. You can immediately unblock the process by typing, selecting and executing 'ROLLBACK TRAN' in the blocking transaction's window. Now repeat this test and replace 'SERIALIZABLE' with 'READ COMMITTED' and you will see that when you first start batch A, you can still execute Batch B simultaneously (which wasn't so with the SERIALIZABLE level).
 
Here are the isolationlevel-enumerator values from system.data:
 
[Flags]
public enum IsolationLevel
{
      // Fields
      Chaos = 0x10,
      ReadCommitted = 0x1000,
      ReadUncommitted = 0x100,
      RepeatableRead = 0x10000,
      Serializable = 0x100000,
      Unspecified = -1
}
 
The BizTalk SQL adapter always uses 0x100000. You can check this by viewing the requested locks in Enterprise Manager:
 
 
Now, I believe the above will rarely be a problem in real-life. You should only expect performance problems when you have a lot of transactions and a lot of simultaneous lock requests for the same heavy resource while having a bad database-design (having no or having the wrong indexes). You should also know that lock waits are perfectly normal: a simple wait for a lock is different from a deadlock. The waiting process will get the lock anyway when the process that's holding the lock completes.
If you use SERIALIZABLE my best advice is to tune you sql statements for performance (also having correct db-design, normalization, the right indexes,...) in order to make your select statement execute as fast as possible .
 
**UPDATED**
 
Is there a solution?
  • If you try to add the 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED' to a select-statement based receive location then you may have no issues at design time. But when you try to add a RL based on this SQL statement in the  BizTalk Explorer you will get a 'The SQL statement must be either a select or an exec' error.
  • You can add ‘With (Readcommitted)’ to the tables in the select, or data modification statement. 'Select * from authors with (Readcommitted) where contract = 1'. This will override the default Serializeable isolation level, and keep the number of locked records to a minimum. Credits go to Dirk Gubbels from Microsoft...
SQL Server locking experts' comments are very welcome...

posted @ Thursday, November 25, 2004 4:35 PM | Feedback (9)

Tuesday, November 23, 2004 #

About publisher policy assembly chaining

I've just found out the hard way that GAC'ed publisher policy assemblies do not chain. When you have a policy.1.0, redirecting the binding of assembly v1.0.0.0 to assembly v1.1.0.0 and also having a policy.1.1, for redirecting the binding of assembly 1.1 to assembly 1.2, this doesn't result in a binding to the assembly 1.2 when your app requests 1.0 (but rather to 1.1). If you want this kind of binding-behavior I guess you will have to use publisher policy versioning.
 
Why do I tell all this? Well, I've never read anything about this before so I thought it would be nice to mention here.
I also want to thank Alan Shi, who confirmed and explained this binding behavior to me. For more excellent information regarding the GAC and Fusion you should definitely visit his blog here.

posted @ Tuesday, November 23, 2004 11:14 AM | Feedback (3)

Wednesday, November 17, 2004 #

The BizTalk Configuration Dilemma

I’ve watched several times Jurgen Willis’ excellent online presentation about the Business Rule Engine (BRE). One of the BRE usage scenarios demoed by him contains a sample orchestration that uses the BRE to dynamically configure a delay time.
This confused me since it added another option to accomplish dynamic configuration of business processes. We are definitely facing a configuration dilemma now; here are some of the alternatives:
 
  • Config Files
    Use the default .NET config files as the store (BTSNTSvc.exe.config) for your key-value pairs or custom types. You can easily read the settings using the default .net classes from inside your orchestrations.
    This is definitely the easiest option. But it makes your business processes host-instance depended (every host instance can be differently configured). It’s also not easily deployable, when having different environments you will have to manually copy paste your configuration sections, you could easily make mistakes. I guess there are no tools available for the business users to manage the values.
 
  • Business Rule Engine
    Although I have the feeling the BRE and its terminology is not really geared towards this simple functionality (storing key-value pairs). Most of the BizTalk included samples use schema-facts, some of them use class-facts but none addresses the config management purpose which was demoed in the presentation.
    I’ve tested a couple of things myself, including calling the BRE from code inside an orchestration by using several Stringbuilder instances or a Hashtable as the argument(s). This seemed a very strange solution to me (it’s not easy to define the rules/vocabularies when having several instances of the same class).  Another option is to create a custom configuration class which gets and sets the values, this will simplify the vocabulary. Or you could always use the classic approach and create a custom schema to hold your configuration values.
 
 
Finally I emailed Jurgen, who appeared to be a very friendly and helpful man. He pointed me out that the BRE is in fact not specifically targeted at this scenario and that, in general, it focuses more on complex types than on using value types (especially when multiple instances are evaluated in the same policy). 

posted @ Wednesday, November 17, 2004 5:25 AM | Feedback (12)

Wednesday, November 10, 2004 #

Executing pipelines from inside an orchestration: Introducing the LOOPBACK adapter

Let's go over some of the out-of-the-box options for executing a pipeline from inside your orchestration.
 
It struck my mind first that the MSMQT adapter IS in fact the messagebox.
 
  1. MSMQT
 
  • Set up a schedule with 1 MSMQT send port and 1 MSMQT receive port sharing the same MSMQT queue name (for example ' loopback' would make a lot of sense)
  • Create a correlation type and set based on the my MSMQT label property.
  • Assign the MSMQT message-label to a newly created GUID inside your orchestration.
 
Try to do a send and a receive and you will see that your pipelines will be executed. As a test I could successfully parse a message from inside a schedule.
 
Another very simple option is using the HTTP adapter, credits go 100% to Scott Colestock. Scott used this as just a temporary approach to get past this problem, and then switched to the loopback adapter below...
 
  1. HTTP
 
  • Use a solicit-response send port 
  • Use bogus HTTP page that simply echoes the content back.
 
<% @ webhandler language="C#" class="LoopbackHandler" %>
using System;
using System.Web;
using System.IO;
public class LoopbackHandler : IHttpHandler
{
   public bool IsReusable
   { get { return true; } }
  
   public void ProcessRequest(HttpContext context)
   {
      using(StreamReader sr = new StreamReader(context.Request.InputStream, true))
      {
         StreamWriter sw = new StreamWriter(context.Response.OutputStream, sr.CurrentEncoding );
         sw.Write(sr.ReadToEnd());
         sw.Flush();
         sw.Close();
      }
   }
}
 
This can be easily explained because it requires no knowledge of correlation types and correlation sets, since you are using request/response ports the whole way. If simplicity is the main goal then this solution is probably superior to the MSMQT one.
 
  1. Custom LOOPBACK Adapter.
 
I also had another idea. Why not make your own loopback adapter by writing a bogus solicit-response adapter that returns a response BizTalk IBaseMessage that is a copy of the original request message. Recreate the original individual message-parts and copy of the request stream to the response stream. It's very simple - download my sample loopback adapter here.
 
  • It's a custom coded VB.NET non-batched but non-blocking (async) adapter that really doesn't do anything.
  • Uses limited memory-footprint, streams to disk. 
  • To install use the MSI package. Don't forget to add the adapter by using BizTalk administration...
  • It auto generates the transmit location URI (in fact it's a GUID). I also added a Boolean property to specify whether you want the original message and part properties to be copied on to the response-message and parts.
 
Here are some of the benefits:
 
  • Trigger pipeline execution from inside your orchestration. Just define your outbound and inbound pipelines and they will be executed.
  • Send pipeline errors can be catched by adding a deliveryfailure-exception handler. Also adapter exceptions can be catched there, but since this adapter really doesn't do anything this will be very rare (at least I hope so).
  • Receive pipeline errors can be catched by adding a general SOAP-exception handler.
  • Execute mappings from inside your orchestration by defining a map on the inbound and outbound port. When you use the later, mapping failures will be catched by the SOAP-exception handler.
  • It's a black-hole adapter if you want. It can be used to ignore the processing of certain incoming messages. Make a send-port, name it 'VANISH' and subscribe to a given message-type or receive-port name for example.
  • It's very useful for doing in-order processing. You can for example receive messages from MSMQT through a pass-through pipeline (which is recommended BTW) and process messages in-order from start-to-end while doing exception-handled parsing/validation/mapping by implementing a serial convoy.
 
Here's a sample project that demonstrates some of the benefits.
 

Remarks:
 
  • The code can definitely be improved. It has been written very quickly in the scope of a POC. Alternatively you could make a better one using the adapter base classes and the wizard. In fact I'm hoping the community will see the benefit of this loopback adapter and someone else will make a better one. I'm not (yet, ha!) a streaming and multi-threading expert.
  • Apparently it is advised to return a read-only forwarding stream to the receive-pipeline. At least until SP1 arrives. I just used the VirtualStream class from the BizTalk Streaming assembly.
  • Do not forget, and as usual: there's no warranty at all. I haven't tested this very thoroughly yet so…use the adapter at your own risk.

posted @ Wednesday, November 10, 2004 3:24 AM | Feedback (19)

Monday, September 20, 2004 #

Leveraging MSMQT acknowledgments

You all probably know that MSMQ stands for 'Microsoft Message Queuing' and MSMQT is the acronym for describing the BizTalk MSMQ adapter. A quick reminder for those who already forgot: the "T" in MSMQT stands for transactional (not “Transport”)
 
Probably less common knowledge is what MSMQ acknowledgments (ACKs) are, so I have chosen this to be the topic for my first post. What are ACKS and in what flavors do they come?
 
Acknowledgments are system-generated confirmation messages that are sent to the administration queues specified by the sending application. When an application sends a message, it can request that Message Queuing return acknowledgment messages indicating the success or failure of the original message.
 
  • A reach acknowledgment tells you that the message reached its destination queue.
  • A receive acknowledgment basically tells you that some application successfully received a message from a queue.

Both acknowledgment types have positive (ACK) and negative (NACK) variants indicating - this is too straightforward - a success or a failure: positive arrival acknowledgments, positive read acknowledgments, negative arrival acknowledgments, and negative read acknowledgments.
 
If you want to get rapidly acquainted with acknowledgments you should definitely read this excellent article on MSDN: Reliable Messaging with MSMQ and .NET (Building Distributed Applications)
 
Personally having no prior experience with MSMQ acknowledgments, I started my first tests having big expectations. I built a .NET application and sent my 1st MSMQ message with an ACK-level set to full_reach and full_receive using a non-transactional admin queue. (my machine is a simple MSMQ independent client so I send to other machines using outgoing queues). Also not wanting to be too haughty I targeted my first message send at a regular MSMQ server. As expected my message arrived quickly at its destination queue where I subsequently could read the message through code.
 
Wonderful, I had 2 ACKs in my sending machine's admin queue:
 
ACK1 MSMQ message class = The message reached the queue.
ACK2 MSMQ message class = The message reached the queue.

Since this first test being a big success I already wondered what would happen if I'd send the same message again, but now targeted to the BizTalk MSMQT adapter.
 
I quickly set up a BizTalk MSMQT receive location with a passthru pipeline and a file send port subscribing to the MSMQT port. After BizTalk created the flat output message I was really surprised - even a bit disappointed at the same time - because I only found 1 acknowledgment in my admin queue:
 
ACK1 MSMQ message class = The message reached the queue.

Where the heck did the receive ack go? Did I make a mistake? I did have a valid subscription and it was consumed correctly because I had a file. After doing some research, newsgroup postings and e-mailing, a very helpful person from MS gave me the answer: 'For Biztalk, multiple "applications" can receive the message and MSMQT doesn't know how many got it, so it was decided that receive ACKs would only confuse the customers.'
 
Slowly getting over my depression I started focusing on the ACK I did receive. I started to think about the opportunities this ACK creates: you now have a level of traceability at the sender's side. For my next test I sent a message to an invalid MSMQT queue - more precisely I used an invalid name being a non existing queue on MSMQT. Admin queue:
 
NACK1 MSMQ message class = The destination queue does not exist
 
  • Event viewer: Destination queue 'wrong queue' cannot be reached. For local BizTalk queues, the receive location may not exist or may be disabled.
  • HAT: Nothing
 
Exactly what I expected! This reminded me of some interesting must-read posts on this subject by Darren Jefford's blog titled MSMQT, Transactional Queues and Xml Validating Pipelines and MSMQT: Debugging and Getting hold of malformed messages.
 
Conclusion: if the sending of a message fails the sender receives a NACK message in the admin queue and eventually after exhaustion of the retries MSMQ places the bad message from the outgoing queue in the dead-letter queue (optional: see below for more information). Darren Jefford advices to always use passthru pipelines for MSMQT receive locations. Now let's ignore his advice and try the opposite. What would happen if I would send a message to an existing queue but an exception is raised from inside the receive pipeline?
 
I quickly configured my MSMQT receive location to use a pipeline implementing the flat file parse (FFDASM) component. Next I intentionally sent a malformed FF message to the MSMQT queue - generating a parsing error. Here is what I got in my admin queue:
 
NACK1 MSMQ message class = The destination queue does not exist

I expected to have a more meaningful description as for example 'Parsing failed', but I received the same - now totally irrelevant - description. As a consequence the message sender cannot see the difference between these 2 different types of errors. I asked my MS contact again and he gave me this explanation: 'because we cannot define new values for MSMQMessage.Class, we were pretty much stuck with the existing ones.' This means, I think, that they were stuck with the standard MSMQ API error enumerators.
 
So here's my conclusion: If you send messages to MSQMT receive locations you should always choose between
 
(A) Use a passthru pipeline on the receive location or
 
(B) Use a custom pipeline but specify a dead-letter queue for the message and/or implement acknowledgments/logic to handle failed messages due to pipeline execution errors.
 
As for the sake of completeness I also want to mention that MSMQT also sends positive ACKS for each successful message receival. This assures us that your message was handled fine and survived pipeline execution without any error.
 
Now having all these extra bits of information regarding ACKS I'd like to finish by issuing a little warning. An example of a bad design would be to create some kind of service that sends messages 1 by 1 to a MSMQT node - while waiting in between each send for an acknowledgment. This would probably work from a functionality point of view but never from a performance perspective. Read this: 'Using the Right Tool for the Right Job' chapter
 
To finish my article I'd like to comment on the overall very fine transcript of the Microsoft Support WebCast - BizTalk Message Queuing in Microsoft BizTalk Server 2004 where Rajan Dwivedi states 'As far as interaction between MSMQT and MSMQ is concerned, MSMQT can receive messages from MSMQ, and it can also send messages to MSMQ without any difference.' Well Rajan, I'm not so sure ;-)

posted @ Monday, September 20, 2004 12:30 AM | Feedback (2)

Custom BizTalk Instrumentation with EIF

The MSBTS_ServiceInstanceSuspendedEvent WMI event is fired by the BizTalk Engine whenever a "message" is suspended. This happens (amongst other reasons) when all send retries fail (for example when a connected system is down) or whenever exceptions occur during the pipeline execution (for example when message validation fails).
 
For this little article I'd like to focus on the first category: outbound suspended messages caused by systems being temporarily unavailable. Usually admins like to receive notifications whenever one of their systems goes off-line. You can set up a NT service that consumes BizTalk MSBTS_ServiceInstanceSuspendedEvents and notifies the admins for example by e-mail (to the Biztalk admin and/or appropriate system admin). They can then fix the problem and bring their failed system back up.
 
Now the problem is that you still have to deal with those suspended messages that sit in the message box as a result of the failure. They simply have to be resubmitted and this can be done using the HAT tool. This can be a quite repetitive task that's very prone to errors (try resending the wrong message). In many cases an automatic solution would make a better one. Let's see what can be done:
 
One could react by upping the retry count to its maximum value? Ok, this would automate things a lot but has 1 very big disadvantage: you lose your notifications because the message will never suspend :-( Who will bring the system back online? You NEED these notifications so this isn't a viable solution: you have to lower the retry count back to an acceptable level. Is there another solution? Yes there is: add your own custom WMI events to BizTalk Server!
 
What if we could add extra custom events that create the functionality to receive notifications upon the retry itself - without requiring a message to be suspended? This sounds very complicated but is in fact a very easy task when you use the Microsoft Enterprise instrumentation Framework to create a custom event class.
 
For those that never heard of it, this is what EIF can do for you! From the EIF README:
 
'The Microsoft Enterprise Instrumentation Framework (EIF) enables you to instrument .NET applications to provide better manageability in a production environment. EIF is the recommended approach for instrumenting .NET applications. It provides a unified API for instrumentation that uses the existing eventing, logging, and tracing mechanisms built into the Microsoft Windows® operating system, such as Windows Event Log, Windows Trace Log, and Windows Management Instrumentation (WMI). Members of an operations team can use existing monitoring tools to diagnose application health, faults, and other conditions.
 
An application instrumented with EIF can provide extensive information such as errors, warnings, audits, diagnostic events, and business-specific events.'
 
The EIF also forms the basis/prerequisite for the Microsoft .NET Logging Application Block. This block represents the 'new' way to do logging /exception management - replacing the older EMAB (exception management application block).
 
Let us - by means of example - add the following events to our BizTalk Server 'event source':
 
  • TransportLostEvent: a system goes down for the 1st time = First failure
  • TransportRecoveredEvent: a system comes back up again = A retry succeeds
 
I have used very basic sample classes for these events. Feel free to e-mail me to get the sample - I haven't got uploads working yet :-(
 
The context of the message will provide us with our basic building blocks and determine when these events have to be triggered. The 'http://schemas.microsoft.com/BizTalk/2003/system-properties' namespace contains 3 unpromoted properties named ActualRetryCount, RetryCount and RetryInterval.
 
  • RetryInterval is a static value representing the value set on the Send Port.
  • RetryCount - on the other hand is - very confusing - not a static value but represents the number of retries still available - and is lowered by 1, by the Engine for each failed transmission attempt.
  • ActualRetryCount, which BTW returns no results when you look for it in the help, is also a dynamic value that is incremented by 1 for each transmission attempt.
 
So how can we make this all fit together, wherefrom can we trigger our events? There are 2 scenarios possible: a custom adapter and a custom pipeline component (for integrating with existing adapters).
 
Here's a sample piece for a custom adapter:
 
'If message transmission succeeded
oProperty = msg.OriginalMessage.Context.Read("ActualRetryCount","http://schemas.microsoft.com/BizTalk/2003/system-properties")
If Not oProperty Is Nothing Then
'A previously failed send operation has now succeeded actualretrycount>0 and msg.TransmitSuccesfull is true)
If System.Convert.ToInt32(oProperty) > 0 Then
myTransportRecovered = New TransportRecoveredEvent
obj = msg.OriginalMessage.Context.Read(InterchangeIDProperty.Name.Name, InterchangeIDProperty.Name.Namespace)
If Not IsNothing(obj) Then myTransportRecovered.InterchangeId = System.Convert.ToString(obj)
'Continue to build and finally raise the event
.
myEventSource.Raise(myTransportRecovered)
Else
'If message transmission failed
'If actualretrycount is 0 then this means that system failed for the 1st time: raise TransportDownEvent
oProperty = msg.OriginalMessage.Context.Read("ActualRetryCount", RetryIntervalProperty.Name.Namespace)
If Not oProperty Is Nothing Then
If System.Convert.ToInt32(oProperty) = 0 Then
myTransportLost = New TransportLostEvent
and so on...
myEventSource.Raise(myTransportLost)
.
A very nice idea would be to develop an "EIF enhanced" version of the adapter base classes that trigger additional events. Anyone interested?
 
I've also succeeded into making a sample pipeline component that raises the TransportLostEvent from inside a pipeline - creating the opportunity to integrate this functionality with existing adapters. I tested this very rapidly/effectively thanks to the pipeline component wizard by Martijn Hoogendoorn...
The downside for pipelines is that - if I'm correct - we have no notion of the current transmission attempt result from inside (the result) so we cannot raise the TransportRecoveredEvent. What we do have, is the result of the previous attempt and the actualretrycount - creating the possibility to trigger the TransportLostEvent upon the first message retry.
 
As a final note always remember that WMI events do have a performance impact. So you may want to just send them to the WTE (trace events) sink if you don't need them and performance is an issue. The nice thing about the EIF is that this can be done dynamically and doesn't require a restart of the 'Event Source' or changing the pipeline. See the configuration section in the readme of the EIF for more info.
 
Here are some stats for the curious - Event sink Average events per second:
 
  • Windows Event Log 220
  • MSMQ 120
  • WMI 520
  • SQL Server Basic Log 300
  • SQL Server Flexible Log 70
  • EMAB with the Windows Event Log 120
     

posted @ Monday, September 20, 2004 12:34 AM | Feedback (2)

Doing fast and easy mapping updates with BizTalk 2004

Do you remember those good old BizTalk 2002 days when you only had to make a couple of clicks through the BizTalk messaging manager to refresh a mapping? Well it's time to share with you a nice technique that makes BizTalk 2004 mapping updates just as easy to make and deploy:
 
  • For this technique to work you have to make sure you always compile and distribute your mappings into a 'mapping only' assembly - this will simplify things a lot. Do not put your referenced schemas inside this mapping assembly.
 
  • Keep always track of the version-number your mapping assembly has (by setting the version number in the assembly config file.). Remember that version numbers are in the format "Major.Minor.Build.Revision".
 
  • Deploy your finished solution into your production environment. This can be done in a variety of ways: using an msi or you could just deploy assemblies manually using the deployment wizard. Usually you make this decision depending on the complexity of your solution.
 
  • Now you discover a mapping error requiring an update after everything is already deployed. You are afraid to touch the installed assemblies - you know how complicated things can get when undeploy redploy. You don't want to break any dependencies or anything...but it's not a breaking change - just a fix - changing a couple of mapping links...
 
  • The solution: Just recompile your updated mappings project and up the version number and deploy your updated assembly using the deployment wizard while leaving your old assembly in place. You can deploy your new assembly to the GAC and optionally - not mandotary - also into BizTalk. This makes then a total of 2 versions of your mapping assembly deployed side-by-side into Biztalk at the same time (the original and the updated one). This doesn’t affect your running solution at all, because BizTalk references mappings strongly, it will still keep using the original assembly from the GAC.
 
  • Now change the .NET assembly binding behavior by inserting a binding redirection into the XML config file.
    You can do binding redirections on both application level (BTSNtsvc.exe.config in our case) and on machine level by updating the machine.config file. You can update config files manually or use the .NET configuration framework mmc snap-in that we will use for simplicity sake. Here's a sample binding redirecting from my machine.config file:
 
  •   <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="StoraEnso.Mappings.Fenix" publicKeyToken="15b134fbf6ea6bf5" />
            <bindingRedirect oldVersion="1.0.0.0" newVersion="1.1.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
 
  • Recycle (restart) the BizTalk host instances - to recycle the app domains that use the mapping assembly. Voila: BizTalk is now using the new version!
 
  • Not happy with the result? Manually remove the binding redirection again or using the snap in, recycle the hosts and you are back to the old version, it's just that easy!
 
For the curious: I've also tested BizTalk assembly redirections using a publisher policy assembly and it seems to work fine. Remember to up the Major or Minor part of the version for this to work. You now have the capability to create an msi that installs/uninstalls an updated mapping assembly.
 
Additionally I'd also like to mention that binding redirections can be used for BizTalk schema assemblies too. This, though, creates extra complications because BizTalk will always match duplicate assemblies to a given message type if you have 2 versions deployed into BizTalk. As a consequence you will have to make all your receives/pipelines what I call 'Strongly Typed' and this indicates extra property promotion work (the type) and I had to play with SchemaWithNone in my code to make FFDASM and other pipeline components work correctly...
 
So I guess - never tested this myself - it's better to only GAC updated schema assemblies - if you'd want to use this technique at all for schema assemblies....
 
A final word of advice: technically it's possible to keep on patching forever and ever - though this would make a very bad practice ;-)

posted @ Monday, September 20, 2004 12:31 AM | Feedback (4)

Tuesday, October 05, 2004 #

Rule engine - Another way to debug the rule engine

This simulates an orchestration callrules action from code:
 
MyArrayList = new System.Collections.ArrayList();
MyPolicy = new Microsoft.RuleEngine.Policy(YourPolicyName);
MyTracer = new Microsoft.RuleEngine.DebugTrackingInterceptor();
 
You will have to create your facts in here. Use TypedXmlDocuments or custom objects (see the BizTalk help for samples)
 
MyArrayList.Add(MyFact1);
MyArrayList.Add(MyFact2);
MyPolicy.Execute(MyArrayList.ToArray(),MyTracer);
MyPolicy.Dispose();
System.Diagnostics.Trace.WriteLine(MyTracer.GetTraceOutput());
 
The above line will redirect the traces to the windows event trace.
Use the excellent debugview utility from sysinternals to view the traces.

posted @ Tuesday, October 05, 2004 5:16 AM | Feedback (0)

Monday, October 04, 2004 #

Flat File Parser Annotations

Here's a presentation containing an overview of the flat file parser annotations that can be manually inserted into the BizTalk message schema. This is part of a presentation I gave at the Belgian BTS user group meeting a couple of weeks ago. There is also a sample project containing different schemas per annotation showing each annotation's purpose. My main source of information was the BizTalk newsgroups where David Downing makes the beautiful weather for this topic. Just for the record: as usual everything is 'AS IS', so there's no warranty at all...
 
BTW this is my first post using the Simple Blog Editor InfoPath form that I found thanks to Capo

posted @ Monday, October 04, 2004 5:23 AM | Feedback (2)

Monday, September 20, 2004 #

1st Post - Welcome!

'Hello world!': These are the words I’d like to welcome you with. During the past couple of months I must have read almost every BizTalk blog available. Each and every one of them has proven to be an incredible source of information. More than once, fellow BizTalk bloggers have inspired me and provided me with extra insights and missing links for my customer projects. You have definitely proven to be one of my biggest assets - something which an independent consultant like me can only dream of. So now it's about time for me to do something in return...

posted @ Monday, September 20, 2004 12:20 AM | Feedback (4)

Copyright © Gregory Van de Wiele

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski