Processing Empty Files in BizTalk

|

Over the past few weeks, I have been working on a particular BizTalk integration project, which required me to process empty BizTalk files (0 byte). The default behavior of FILE adapter is to delete empty BizTalk files, and then raise an event. At this point, the empty BizTalk file is deleted before it reaches pipeline on the way to BizTalk MsgBox. Unfortunately, there is no way to do a routing based on the filename whether in a pure message scenario or by using an orchestration.In order to process these empty BizTalk files, one could extend the File Adapter that is part of SDK (Image 1.1). Add the 3 projects in a Visual Studio Solution as indicated in Image 1.2.

Image: 1.1


Image: 1.2

Below are Key Steps to Process Empty Files in BizTalk:

Step 1. Build the BizTalk solution, GAC Microsoft.Samples.BizTalk.Adapter.Common.dll.

Step 2. Registry Key.

Use the StaticAdapterManagement.reg registry key file given in the sample and update the locations of the dlls mentioned in it. Microsoft advocates adding an additional string for 64 bit machines; however, I did not do this step. It still worked!

Step 3. Go to BizTalk admin console and  add the new EMPTY FILE adapter. At this point, you may receive a similar error to:

The system cannot find the file specified.

/C:Program Files (x86)Microsoft BizTalk Server 2009SDKSamplesCustomAdaptersDevelopmentFile AdapterRuntimeMicrosoft.BizTalk.SDKSamples.Adapters.DotNetFile.Runtime.dll

This BizTalk error threw me off a bit, as the registry key file did not contain this path. The above error led me to wonder why BizTalk was even looking for this path in the first place. I completed a quick search for this file in the entire registry, and I did find a few references. Honestly, I have no clue what these references were being used for but for some reason BizTalk was reading them from the registry key. I decided to rename the key for these entries without deleting it. I was then able to add the adapter to BizTalk successfully.

Step 4.  With the new EMPTY FILE adapter added, I allocated it to the appropriate BizTalk host in order to use it in the send/receive port. While setting the receive handler for this newly added adapter, I got the following error:

The Messaging Engine encountered an error when initializing the receive adapter “EmptyFile”, HRESULT:”Property /Config/pollingInterval not found on adapter configuration XML.”.

At this time, I chose to debug the code in order to find the point of error. I found the error in method. This is a bug in Microsoft supplied code

ExtractPollingInterval in file ConfigProperties.cs under project Microsoft.Samples.BizTalk.Adapter.Common.csproj

Update the following code

long pollingInterval = ExtractInt(document, “/Config/pollingInterval”);  string pollingUnitOfMeasureStr = Extract(document,”/Config/pollingUnitOfMeasure”, “Seconds”);

To…

long pollingInterval = Convert.ToInt32(IfExistsExtract(document, “/Config/pollingInterval”,”5″));
string pollingUnitOfMeasureStr = IfExistsExtract(document, “/Config/pollingUnitOfMeasure”, “Seconds”);

Or update the root name of ReceiveHandler schema to Config. I did the code change, but not the schema.  I was then able to configure this new custom FILE adapter to receive an empty file. In order to get a handle on the empty file, it was necessary for me to go to method PickUpFilesAndSubmit which is part of DotNetFileReceiverEndpoint.cs under DotNetFile.csproj

The line of code that got me the handle to the incoming file as:

if (item.Length == 0).

Once I got the handle, I was able to add my logic to deal with the incoming empty BizTalk file. In my case, I chose to add a string “EmptyFile” if the incoming file was empty. I would then detect this file with this added string in the send side using the same custom adapter, and assigning  0 bytes to it

Unfortunately, this solution requires tampering with contents of an empty BizTalk file. This may be to acceptable in some cases, and for my purposes it was acceptable.

Send Side Changes:

To intercept the EmptyFile (file with “EmptyFile” string) on the send side, I utilized the method: ProcessMessage in file DotNetFileTransmitterEndpoint.cs under project DotNetFile.csproj.

At this point, I input the following snippet after cloning the stream. This writes the empty file.

StreamReader sr = new StreamReader(Stream);string fileContents = sr.ReadLine();

if (fileContents.Contains(“EmptyFile”))
{
fileStream.Write(new byte[0],0,0);
return null;
}

Dynamic Send Port:

In order to get this adapter to work with Dynamic Send port following changes were needed:

1. Use DotNetFILE:// instead of FILE:// in orchestration for setting dynamic address


2. Use following code to extract destination string from the context properties:

filePath = message.Context.Read(“OutboundTransportLocation”, “http://schemas.microsoft.com/BizTalk/2003/system-properties”).ToString();

Use this destination string to parse the final destination of the file and add code to write the file to that location.

Leave a Reply