Thursday, January 26, 2006

Custom Pipeline Woes

In one of my project, the source system was sending 2 almost similar messages to Biztalk. The only difference was the root node name. I had 2 ways of dealing with it.

Solution 1:


1) Create separate document schemas
2) Create separate Receive Pipelines referring to each document schema
3) Use a map to change the root node name so to have exactly same message that can pass through the common orchestration thereafter.

Pros:

1) Less Development time
2) Easy message retrieving in case of failure

Cons:

1) Additional artifacts required in form of additional schemas and pipelines.
2) Low in performance and high in memory usage as we have to use extra map.

Solution 2:

Use a custom pipeline component that will replace the “root node” name to a common node name.

Pros:

1) Cleaner and Faster

Cons:

1) More development time
2) If error handling is not proper then the entire message is lost. This is because there is no persistence to messagebox in the pipelines.

Whereas the first solution is very easy, the second is relatively difficult. I tried the second one for simple reason that it was challenging and I thought I could do it within reasonable time that I had. I started by following the standard procedure for developing custom pipeline components. I used the “FixMsg” custom pipeline sample from “SDK” as my base code. It is located at “..\Program Files\Microsoft BizTalk Server 2004\SDK\Samples\Pipelines\CustomComponent”. This saved me some time in not “reinventing” the wheel. I worked on the “Execute” method and converted the Stream to Byte and then Byte to string. Then I tried replacing the required node in string and then tried to convert back the new string back to stream. Since pipeline only deals with streaming data. I ensured that the return is a “stream”. My approached looked quiet logical to me but the results were NADA. This string replacement did not actually work as I was not able to pass the “stream” back to the next stage of the pipeline. Then, I thought of using XPath. But since pipeline deal with streaming data whereas Xpath requires the whole message to be loaded into memory. I could not use the normal Xpath but I could “streaming Xpath”. This is called “forward only” Xpath. I tried “cloning” the stream so I can use XMLReader class on it. But could not go anywhere, then I gave up the solution as I was running out of time. I lost this challenge!! But, I will definitely revisit it once I get some “breathing space”.

Any inputs will be welcome.

Tuesday, January 17, 2006

Capturing ACKs and NACKs

I am presently working on "File Mover" application. This application will replace existing VB application to move files from point A to point B based on the filename. Filename contains the send location address. I am populating a SQL database to track the file moved from point A to point B. One of the problems I am having is to capture the "Error in Transmission". This is tough to capture because File adapter transmission is separate from Orchestration process. Once orchestration is complete, it does not really care if message was sent or error out. For this we need to use concept of ACKs (Acknowledgements) and NACKs (Negative Acknowledgements). ACKs indicate successful message transmission and NACKs indicate failures in transmissions. Since I am using one way "asynchronous" FILE transmission these come handy. Some readers may ask why not use Request-Response. The reason is that they can only be used for HTTP adapter when there is a response that can be captured. For File adapter transmissions, we can only use ACKs and NACKs

Follow steps below and that is all you need to capture ACKs and NACKs.

1) Put Send shape in a Scope and make "Transaction Type" as "None".
2) Set "Synchronized" property to "True".
3) Mark Orchestration with Delivery Notification = Transmitted
4) Use "Catch Exception shape"
5) Select the following exception type in properties:
"Microsoft.XLANGs.BaseTypes.DeliveryFailureException"
6) Call the insert method for populating database in the "Catch" shape.
8) Put the "Send" shape to save the "bad" files to a folder.
7) Then PUT the "terminate" shape in the "CATCH shape".





Wednesday, January 11, 2006

Wonderful Cruise!

The other day I was talking to one of my co worker (Abhi). He also maintains a Biztalk blog http://biztalkland.blogspot.com. We discussed about putting more non-technical stuff on the blob. We gave argument for and against it. How it will look out of place ...blah..blah. Finally, we decided that Blog is a medium to express. So there are no Rules for it as such. People might argue on this. Everyone is entitled to his/her opinion. After the conversation, I decided to trickle some personal stuff now and then.

I went on cruise with my wife. It was our "HoneyMoon" cruise. Even though it took place after 6 months of our marriage. I had just enough time to get married in June so we did not push for Honeymoon that time. Although we did went to India for our Reception as we got married in USA. After we came back she became busy with her residency and I went down with my project. Xmas and New Year stretch was good for the break we needed and we used that time to hop on a ship and hit the Caribbean. We went to San Juan, Saint Maartin and Saint Thomas. I personally loved Saint Thomas. The beaches are pristine there. We had tons of fun before coming back to Sub Zero temps. I am also putting some pics from our trip!



Tuesday, January 03, 2006

FileMove Application and "MessageBox" error

Recently, I was asked to create an application that will replace an existing VB application. The application was to move the Files from a common location and drop them to a different destination based on the FileName. The File Name had the destination name in it. This is what I did:

1) Created a simple Orchestration with single receive port that will have filter for every possible file. i.e. pdf, dat, xml, txt etc.

2) Create a Dynamic port

3) Create a "Helper" class in VB.net. This will parse the incoming file name to extract the URI for dynamic port. This URI will determine where the file should be routed too.

I set up the whole project but found some interesting facts:

1) If the URI is blank for some reasons. You will get the following error in the eventvwr.

"Exception occured when persisting state to database".

2) The syntax for the URI for dynamic port will be.

file://servername/sharedfolder/Filename.

The start of the URI will tell the port that it is a "FILE" adapter. The rest will give the complete path to drop the file.

3) While using File.ReceiveFileName in the expression share. It will not only give the whole filename but also the path of the receive folder. In order to get the actual FileName, one will have to parse the whole path string.