Interesting tech stuff I come across day-to-day. Mainly around Biztalk and .NET 3.0

SQL Adapter and Debatching. Beware when you process a message that contains consecutive empty elements, debatching will fail.

Wednesday, February 21, 2007

For how to configure SQL Adapter and Debatching see the article writtin by Richard Seroter

This problem occurs when you process a message that uses a document structure that resembles the following.

<DDLService xmlns="http://www.digitaldeposit.net/schemas/SQL">

<CustomerActivationMessages AccountNumber="12345" DDLServiceType="ORDERRESPONSE" DDLServiceName="ORDERRESPONSE" CompanyName="XYZ" CountryCode="GB" />

<CustomerActivationMessages AccountNumber="98765" DDLServiceType="ORDERRESPONSE" DDLServiceName="ORDERRESPONSE" CompanyName="ABC" CountryCode="GB" />

</DDLService >

Envelope Schema: DDLService

Document Schema: CustomerActivationMessages

In our solution, SQL Adapter submits the above message via XmlReceive (used for debatching) pipeline into Biztalk. As soon as the SQL adapter polling starts we started to see the following exception message:

There was a failure executing the receive pipeline: "Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Source: "Pipeline " Receive Port: "Receive.Internal.SQL.1Way.AllPollingService.ActivationMessages" URI: "SQL://SERVER/SchOrderPolling/ORDERRESPONSE/ORDERRESPONSE/902971" Reason: Unexpected event ("document_start") in state "processing_empty_document".

Little bit of search revealed its a known issue with Biztalk 2006 (See the KB Article http://support.microsoft.com/kb/927741) and it applies to any message which contains consecutive empty elements as shown in the beginning of the article. If you notice the message carefully, you can see there is only root element with few attributes and no content element(s).

You got few options to resolve this problem, if you are flexible with the schemas you can add ELEMENTS along with FOR XML AUTO in your SQL Query as shown below

FOR XML AUTO, ELEMENTS

which will result in following xml

<DDLService xmlns="http://www.digitaldeposit.net/schemas/SQL">

<CustomerActivationMessages>
<AccountNumber>12345</AccountNumber>
<DDLServiceType>ORDERRESPONSE</DDLServiceType>
<DDLServiceName>ORDERRESPONSE</DDLServiceName>
<CompanyName>XYZ</CompanyName>
<CountryCode>GB</CountryCode>
</CustomerActivationMessages>

<CustomerActivationMessages>
<AccountNumber>98765</AccountNumber>
<DDLServiceType>ORDERRESPONSE</DDLServiceType>
<DDLServiceName>ORDERRESPONSE</DDLServiceName>
<CompanyName>ABC</CompanyName>
<CountryCode>GB</CountryCode>
</CustomerActivationMessages>

</DDLService >

or, there is a hot fix available from Microsoft at http://support.microsoft.com/kb/927741.

Nandri!

Saravana

Labels:




BizTalk Developers, have you enabled DTA Purge and Archive (BizTalkDTADb) SQL job on your development machine?

Tuesday, February 20, 2007

In development machines, BizTalk developers normally tend to enable full body tracking of messages they process inside the BizTalk server for debugging purpose. As BizTalk Server processes more and more data on your system (over a period of time), the BizTalk Tracking (BizTalkDTADb) database continues to grow in size. Unchecked growth decreases system performance and may generate errors in the Tracking Data Delivery Service (TDDS). In addition to general tracking data, tracked messages can also accumulate in the MessageBox database, causing poor disk performance.

According to this MSDN article http://msdn2.microsoft.com/en-us/library/aa560754.aspx

"By default, the DTA Archive and Purge job is not enabled. You must first configure and then enable the job."

I haven't enabled the job after BizTalk server installation on my development machine and recently when I visited the SQL Data folder for something else I saw this shocking file size (shown below after 6 months of usage). My BizTalk tracking data file is 3.05GB.

Purge tracking data:

BizTalk 2006 got some nice Stored Procedures and SQL Jobs to Archive and Purge the tracking database. BizTalk 2006 gives you an option to Archive and Purge the tracking data or just purge the data without archiving. In a development machine we don't need to maintain the archived tracking data, so we will just purge it periodically.

As soon as I saw the data file size of 3.05GB, first thing I did was configured the DTA Purge and Archive SQL job to just purge the tracking data as explained in the article http://msdn2.microsoft.com/en-us/library/aa578470.aspx

Long story short:

1. Change the SQL Statement inside "DTA Purge and Achieve" SQL Job to

declare @dtLastBackup datetime set @dtLastBackup = GetUTCDate() exec dtasp_PurgeTrackingDatabase 1, 0, 1, @dtLastBackup

If your data file size is too big (like mine 3.05GB) after configuring DTA Purge and Achieve SQL job don't go and run the SQL Job directly, due to the volume of data present in the tracking database, it will take very long time to process the backlog. Instead do a manual purge first as explained in this article

http://msdn2.microsoft.com/en-us/library/aa561918.aspx

Long story short:

1. Stop all BizTalk/IIS service (SSO, Rule,EDI,Host Instances)

2. Open SQL Management Studio and run the following stored procedure under BizTalkDTADb database as shown below:

EXEC  [BizTalkDTADb].[dbo].[dtasp_PurgeAllCompletedTrackingData]

The stored procedure will be executed very quickly, mine took less than 10 seconds (remember my data file size was 3.05GB).

Shrink your BizTalkDBADb via SQL Management Studio:

Right-Click on the BizTalkDTADb database inside management studio and select

Tasks => Shrink => Database, and click "OK"

Now, look at the size of the BizTalkDTADb.mdf file, its shrinked to the absolute minimum value.

Configure the SQL Job to run periodically (every 1 minute)

After performing the steps above (once the tracking data is purged)  "DTA Purge and Archive (BizTalkDTADb)" SQL Job will run instantaneously without any wait. Now, you can enable the job to run periodically.

 

Nandri!

Saravana

Labels:




"BizTalk Server 2004: Receieve Pipeline woes v2" by Charles Young, I guess description for "Seekable streams and MAPS" is incorrect.

Monday, February 19, 2007

Charles Young has written this article "Receive Pipeline Woes V2"  few months back. It's one of the very good articles out there, which explains some of the insights of BizTalk Server internals. But under the heading "Seekable Streams" it appears that the description is not correct. Recently, I came across a strange problem with custom pipeline component and Biztalk MAPs.

My custom pipeline component does very simple task something like reading the incoming message, logging it in the database and putting the message back into the stream using MemoryStream. I can't use the DATA property of IBaseMessage, because I'm using HTTP adapter which gives a Network stream that's not Seekable. Accessing "Position" property or changing the "Seek" position will throw an exception ("method not implemented"). So, I need to populate a local MemoryStream by buffering the input stream in order to do any manipulation on the complete message I received via HTTP adapter inside my pipeline component.

Charles Young in his article (under Seekable Streams heading) says "The first of the two problems is that BizTalk 2004 fails to execute inbound maps over seekable streams.   It is as simple, and as brutal, as that.   If, after a pipeline has completed its work, it returns a message whose body part contains a seekable stream, and if BizTalk matches an inbound map to the MessageType property of the message, the map will always fail with a “The root element is missing” error.   If the stream is non-seekable, and positioned at the beginning of the stream, the map will succeed (unless, of course, there is some other problem)."

I've just put together a sample here, which shows the problem is due to the way you handle stream and the way you flush the stream inside your pipeline component and its nothing to do with whether the stream is seekable or not.

The sample application (Download it here) contains the following artifacts

1.LogMessageWithStreamFlush (Pipeline Component)

2. LogMessageWithoutStreamFlush (Pipeline Component)

3. Receive.LogMessageWithStreamFlush (Biztalk Receive Pipeline)

4. Receive.LogMessageWithoutStreamFlush (Biztalk Receive Pipeline)

5. Tester.XSD, Developer.XSD and Tester2Developer Biztalk Map.

In the sample application Biztalk receive pipelines are configured with appropriate pipeline component (i.e .Receive.LogMessageWithStreamFlush BizTalk pipeline component will have LogMessageWithStreamFlush pipeline component in the Decode stage). The custom receive pipelines receives the incoming message, reads it completely into a local buffer, and then puts the message back into the stream via MemoryStream. A map will be applied on the receive port to transform the message.

Download the Sample. 

To setup the project

1. Copy the zip file to C:\BTSSamples and open the solution SeekableStreamsAndMaps.sln

2. Compile and Deploy the project from Visual Studio.

3. Copy the pipeline component dll "DDL.Samples.SeekableStreamAndMaps.PipelineComponents.dll" to "Pipeline Components" folder under Biztalk 2004/2006 installation directory (normally under c:\program files\microsoft biztalk server 2004(2006).

4. Open Biztalk Adminstrator console. Right-click on the application "SeekableStreamsAndMaps" and import the binding file "binding.xml" from the sample download.

5. Restart biztalk host instance.

Configuration:

Two receive ports (FILE Adapter) are created one with "Receive.LogMessageWithStreamFlush" pipeline and another with "Receive.LogMessageWithoutStreamFlush" pipeline component. Both the Receive ports has got the map "Tester2Developer" which transforms the incoming "Tester" message into "Developer" message.

A send port (FILE Adapter) is created with a "Filter" expression subscribed to messages received via any of the Receive ports we configured in the previous steps.

Execution:

1. Copy and paste the sample message "Tester.xml" (from FileDrop\MSG_SAMPLES) into the folder MSG_IN_WITH_STREAM_FLUSH, you'll see the expected transformed output "Developer" in the output folder "MSG_OUT"

2. Copy and paste the same sample message into the folder MSG_IN_WITHOUT_STREAM_FLUSH, then you'll see the exception as shown below in the event viewer

The Messaging Engine failed while executing the inbound map for the message coming from source URL:"C:\BTSSamples\SeekableStreamsAndMaps\FileDrop\ MSG_IN_WITHOUT_STREAM_FLUSH\*.xml" with the Message Type "http://www.digitaldeposit.net/samples#Tester". Details:"Root element is missing."

The exception is same as what's Charles Young mentioned in his article.

So, What's the difference between two pipeline components:

Below is the code from Execute method of the pipeline component LogMessageWithStreamFlush, which works fine without any issue.

string message = GetMessage(inmsg);

//Log the message to DB or Filesystem or anywhere you like
System.Diagnostics.Debug.WriteLine(message);

//Promote MessageType
string btsNamespace =  "
http://schemas.microsoft.com/BizTalk/2003/system-properties"
inmsg.Context.Promote( "MessageType",  btsNamespace, "http://www.digitaldeposit.net/samples#Tester");  //Hardcoded for the demo

//Write the message back into inmsg stream
MemoryStream memStream = new MemoryStream();
StreamWriter sw = new StreamWriter(memStream);
sw.Write(message);
sw.Flush();
memStream.Flush();
memStream.Position = 0;

inmsg.BodyPart.Data = memStream;
inmsg.BodyPart.Data.Position = 0;

return inmsg;

In the second pipeline component(the one which throws the exception LogMessageWithoutStreamFlush ), I've just commented the two statements which Flushes the stream sw.Flush() and memStream.Flush(). You can see from the above code, I've used MemoryStream to put the message back into the IBaseMessage body part. MemoryStream is fully seekable, you can put the position of the Stream anywhere within the boundary since I got memory as the backend data store. So, it proves the reason why MAP is failiing with "Root element is missing" is purely because we didn't flush the stream, which resulted in empty content of the stream when the MAP starts to pull it.

NOTE: This method is quite expensive and should not be used for high volume systems. As Charles Young explained in his article you should wrap the original stream in a new stream object that processes the data on the fly during read operation, making it stateless. But in my case we were expecting one message every 1 hour once, so its not worth spending so much time on writing a proper stream handing pipeline component.

Labels:




biztalk247.com(BETA) new content.

Thursday, February 15, 2007

I need to thank everyone who visited biztalk247.com on the lauch day and also people who posted the information in their blogs, I got few emails and comments regarding the site, that's really great and encouraging. The site is all about community content, so I request you to send me details if you feel it should be there on biztalk247.com to help new comers and advanced users.

A guy with same name as mine ( :-) )left a comment in the blog yesterday saying "Pro Biztalk 2006" book detail is missing in the book section. I added it this morning. Thanks Saravanan for pointing this out.

If you let me know missing content. I'll add it within 24hours. That's a promise.

Unrelated topic: I watched this video this morning, very intersting "A hour with Bill Gates", where he talks about everything Vista, Xbox, Zune, Google, Virtual Earth, IP TV etc, etc. 

Nandri!

Saravana

Labels:




biztalk247.com (BETA) went live on Feb 14th Valentine Day.

Tuesday, February 13, 2007

I've been working on the project biztalk247.com for nearly 10 weeks now. I guess it's time to make it public. Just to mark the occation special I'm launching it on Valentine's Day.

Some of the key functionalities of the site

1. Got pointers to most of the BizTalk resources available out there from one place, organized in an easy to navigate format.

2. Customized search functionality for BizTalk only resources.

3. Brand new BLOGS aggregator for BizTalk only BLOGS.

4. Quick preview of all the BizTalk blogs in one screen (latest 3 items from each blog).

Visit the site to see all the resources.

Please be aware I put the BETA stamp on it to be on the safe side (As all companies do :-)). Exception handling and error notifications are in place, so I'll wait for a reasonable time and remove the BETA status accordingly after fixing bugs that arise during the warm up period.

I need to thank my lovely wife Gowri , who by profession is a Software Tester helped me in testing the website while she is in her maternity holidays (while the baby is sleeping!! of course). Another person I need to thank is my 9 weeks old son Aryaa who didn't give us too much trouble while we were working late nights and weekends.

Visit the site  http://www.biztalk247.com and give us your valuable feedbacks. You can use the Comments section on the lower left hand side, or you can use "Contact US" form.

The site has TrackBack options as well powered by HaloScan, please do add trackbacks if your blog support it.

Nandri!

Saravana

Labels:




Changing FEED URL to FeedBurner

Monday, February 12, 2007

Hello All,
Due to the rich statistics information given by FeedBurner I decided to move my feed URL to FeedBurner permanently.

My blog aggregator and current FeedBurner statistics shows I've around 25 subscribers. Even though it’s not a great number I don't want to lose them because of the move. I took enough time before making this decision. I'm going to remove all the links to my current feeds (Atom 0.3, Atom 1.0, RSS 2.0) and just going to publish my new contents to the following FeedBurner feed URL in the future.

For easy copy and paste:
http://feeds.feedburner.com/SaravanaKumar

With Link
http://feeds.feedburner.com/SaravanaKumar

I kindly request you to take some time to update your aggregators with the URL mentioned above straight away.

Regards,
Saravana

Labels:




Biztalk 2006 SQL Adapter polling bug. Potentially you can bring Biztalk Server to halt within few minutes.

Scenario:

We send product catalogue to our partner on regular basis via SFTP. There are 3 different types of catalogue message FULL CATALOGUE, PRICE DELTA, and AVAILABILITY DELTA. Price Delta and Availability Delta messages are send every hour, whereas FULL CATALOGUE will be send only once in a month (message size is roughly around 10MB).

Architecture:

Architecture is quite straight forward we have configured a BizTalk "Receive Port" with 3 "Receive Locations" using SQL Adapter. The SQL Receive locations got different polling interval settings as shown below.

PRICE_DELTA: Polls every 1 hour.

AVAILABILITY_DELTA: Polls every 1 hour

FULL_CATALOGUE: Supposed to poll every 720 Hours once.

Through some filter conditions corresponding "Send Ports" will pick up the message and transfer it to our parter via SFTP.

So, where is the bug?

As soon as you enable the FULL CATALOGUE (with 720 Hours polling interval) SQL "Receive Location", you'll see hundreds of messages flooding into your BizTalk server via the SQL Receive Location. If you don't notice it straight away with in minutes you'll have 1000's of messages coming non-stop into BizTalk server and to Message Box, blocking all the network traffice, maximum memory utilization in the Biztalk Host machines and SQL Server.

In our case the effect was pretty bad. We did the configuration at end of business and left it over night. Next day morning, Our Biztalk Server disk space was full (because we temporarily write this particular file to local disk for logging purpose), Event viewer was full of Error Messages related to SQL, pretty much both the BizTalk and SQL machines were  useless.

We started analysing the problem and figured out SQL Adapter polling is working without any issue upto 596 hours, you put any value above 596, your SQL Adapter will start polling messages every 10millisecond or so non-stop clogging the whole Message Box.

Some dissection into Microsoft.Bizatalk.Adapter.SQL.dll

Out of curiosity I just went to figure out the root case for this bug. Lutz reflector came handy to do some dissection of the Microsoft.Bizatalk.Adapter.SQL.dll, which revealed the next polling interval is calculated by the method GetNextActivationTime() inside the TimeIntervalSchedule class, luckily the reflector is showed me the source code as well.

The problem here is "seconds" properties is of type integer (Int32) so the maximum value it can hold is 2147483647. The polling logic will be ok till 596 hours. (i.e 597 * 60 * 60 * 1000 = 2145600000 MilliSeconds), But if you try putting anything bigger than 596 is going to exceed the maxmimum threshold value for Int32 and the function is going to return a DateTime value in the past, which will result in constant polling by SQL Adapter non-stop thinking it has some work to do. Unfortunately in our case it ended up in one of the biggest messages in our system (10MB).

Reproduction of the BUG using windows application. 

You can easily reproduce this behaviour by writing this simple code.

private void button1_Click(object sender, EventArgs e)
{
int f = 597 * 60 * 60;
MessageBox.Show(GetNextActivationTime(f).ToString());
}
public DateTime GetNextActivationTime(int seconds)
{
//return (DateTime.Now + TimeSpan.FromMilliseconds((double)(0x3e8 * seconds)));
return (DateTime.Now + TimeSpan.FromMilliseconds((double)(1000 * seconds)));
}

When I tested this code on 08 Feb 2007, I got the following results

For 596 hours : 05/03/2007 08:47:23

For 597 hours:  14/01/2007 16:45:39 (which is in the past)

Changing the datatype from int to uint will produce the correct result.

So, what's the solution?

1. Option 1: Restrict the User Interface in SQL Adapter to certain values, in our case not more than 597 hours. There is bug in the UI as well, it just throws an exception saying you can enter value more than 65535 (max of uint) inspite of you choosing hours, minutes or seconds.

2. Option 2: SQL Adapter code need a fix.

Sample Application for Download

I'v just put a sample Biztalk Application you can use to see this behaviour. It got 1 Schema to support SQL Adapter, 1 SQL Receive port and 1 FILE send port to "C:\temp". The SQL Adapter will poll data from BtsMgmtDb, here is the query I've used

SELECT NAME, DATEMODIFIED FROM adm_HostInstance FOR XML AUTO

Default binding got the value of 596 hours, which is OK, change it to 597 and see how many messages you are getting on your C:\Temp folder.

Note: Disable the "Receive Location" to stop polling after a minute or so. Dont forget to disable the SQL Receive location after the experiment.

Nandri!

Saravana

Labels:




My white paper published on msdn.microsoft.com/biztalk homepage

Monday, February 05, 2007

Last month I've written an article about Using design time properties in Biztalk Server. Initially the white paper was published on the download section of Microsoft site and there was no link from Biztalk pages.

This morning I bumped into msdn looking for some other resource and found my article right on the home page of biztalk as a very first link

Thanks Luke and editors for making this happen.

Nandri!

Saravana

Labels:




How to create an invisible .NET Application?

Formless application or in my terms invisible .NET applications. I recently end up in a situation where I want to run my console application on a regular schedule via Scheduled task. Problem with that is, it opens ups the schedule every time it runs the application.

There were few suggestions in the newsgroups to create a Windows NT service, or WinForms application and make the form invisible etc, etc. None of them were appropriate for me.

At last I ended up with a quick and efficient fix.

Go to project properties and set "Output Type" to "Windows Application" for your Console application.

Now, I can't see the console anymore, and the application runs in the background quietly.

Nandri!

Saravana

Labels: