System Testing BizTalk Applications with BAM & Xlsb File Generation

In the past I have noticed that system testers find it difficult to test middleware applications such as those implemented using BizTalk. System testers generally don’t want to read BizTalk xml messages dumped out to disk, they like to be able to query for their test results via some form of GUI. Many are adept at writing SQL to return result sets containing the test data they want to analyze.


I came up with the idea of using BAM relationships between different activities within a single view to log before and after snapshots of BizTalk messages. So when messages were transformed by maps, orchestrations or the BRE system testers could test those transforms. You can then give system testers’ access to the BAM Portal Website where they could view and query these before and after snapshots and match the actuals against the expected results to pass or fail their tests.


This solution for system testing only works for certain scenarios’ with certain types of schemas as each message logged cannot contain repeating records if it is to be logged to BAM.


So what am I on about? Take a single record schema which validates an xml message like the one below as I said before this technique won’t work with messages which contain multiple records.


   <ns1:SampleTransaction TransactionID=”123456″ ProductName=”ABC” Amount=”1234.56″ Quantity=”24″ xmlns:ns1=”http://SynbogalooSamples/SampleTransaction/1.0.0.0″ />


Each time a map, orchestration or business rules were applied to a message I wanted to send messages to BAM so I was basically just logging messages to BAM each time the contents of the message changed. I used BAM relationships to associate the message before it was transformed to the message after it was transformed so the tester could assess whether the transformation worked.


OK this was all easy but very time consuming using the Excel add-in to create the xlsb files for each schema so I wrote a simple xlsb file generator. Note: For this code to work with schemas that have xsd types other than DateTime, Integer, Double and String you will need to add to the switch statement in the CreateActivity method.


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;


namespace BAMXslbGenerator
{
    class Program
    {
        private const string UCName = “Name”;
        private const string LCName = “name”;
        private const string View = “View”;
        private const string BAMDefinition = “BAMDefinition”;
        private const string BAMDefinitionNamespace = “
http://schemas.microsoft.com/BizTalkServer/2004/10/BAM“;
        private const string Extension = “Extension”;
        private const string OWC = “OWC”;
        private const string OWCNamespace = “urn:schemas-microsoft-com:office:excel”;
        private const string ActivityView = “ActivityView”;
        private const string ActivityRef = “ActivityRef”;
        private const string Activity = “Activity”;
        private const string Alias = “Alias”;
        private const string CheckpointRef = “CheckpointRef”;
        private const string Id = “ID”;
        private const string Checkpoint = “Checkpoint”;
        private const string XpathToAttribute =
            “(//*[local-name()=’element’])[last()]/*[local-name()=’complexType’]/*[local-name()=’attribute’]”;
        private const string DataType = “DataType”;
        private const string DataLength = “DataLength”;
        private const string Length = “length”;
        private const string MaxLength = “maxLength”;
        private const string XpathToLength = “*[local-name()=’simpleType’]/*[local-name()=’restriction’]/*[local-name()=’length’]/@value”;
        private const string XpathToMaxLength = “*[local-name()=’simpleType’]/*[local-name()=’restriction’]/*[local-name()=’maxLength’]/@value”;
        private const string SqlDateTime = “DATETIME”;
        private const string SqlNvarchar = “NVARCHAR”;
        private const string SqlInt = “INT”;
        private const string SqlFloat = “FLOAT”;
        private const string XsdDateTime = “xs:dateTime”;
        private const string XsdString = “xs:string”;
        private const string XsdInteger = “xs:int”;
        private const string XsdDouble = “xs:double”;


        private static StringBuilder xlsbText = null;


        static void Main(string[] args)
        {
            try
            {
                //Check for help
                if (args.Length == 0)
                {
                    ShowUsageMessage();
                }
                else if ((args[0] == “/?”) || (args[0] == “/help”))
                {
                    ShowUsageMessage();
                }
                else
                {
                    //Parse out command line arguements
                    string xlsbFileNameArg = GetCommand(“/x”, args);
                    string viewNameArg = GetCommand(“/v”, args);
                    string activityNameArg = GetCommand(“/a”, args).Replace(“[“,””).Replace(“]”,””);
                    string schemaArg = GetCommand(“/s”, args).Replace(“[“, “”).Replace(“]”, “”); ;


                    if (xlsbFileNameArg != string.Empty && viewNameArg != string.Empty
                        && activityNameArg != string.Empty && schemaArg != string.Empty)
                    {
                        string[] activityNames = activityNameArg.Split(new string[] { “,” }, StringSplitOptions.None);
                        string[] schemas = schemaArg.Split(new string[] { “,” }, StringSplitOptions.None);


                        GenerateXlsbXml(viewNameArg, activityNames, schemas);
                       
                        //Write out the file
                        File.Delete(xlsbFileNameArg);
                        File.AppendAllText(xlsbFileNameArg, xlsbText.ToString(), Encoding.Unicode);
                    }
                    else
                    {
                        Console.WriteLine(“Incorrect arguements!”);
                    }
                }
            }
            catch (System.Exception ex)
            {
                Console.Write(ex.ToString());
            }
        }


        private static string GetCommand(string commandToken, string[] args)
        {
            string commandValue = string.Empty;


            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == commandToken)
                {
                    commandValue = args[i + 1];
                    break;
                }
            }
            return commandValue;
        }


        private static void ShowUsageMessage()
        {
            Console.WriteLine(“Generates an xlsb BAM definition file conaining one view and multiple schema definitions to log to BAM.”);
            Console.WriteLine(“Syntax: BAMXlsbGenerator”);
            Console.WriteLine(“Commands:”);
            Console.WriteLine(“\t/x \txlsb file name”);
            Console.WriteLine(“\t/v \tBAM View definition name”);
            Console.WriteLine(“\t/a[] \tActivity names enclosed in [] comma separated, there must be one activity name per schema.”);
            Console.WriteLine(“\t/s[] \tSchema names enclosed in [] comma separated, there must be one schema name per activity.”);
            Console.WriteLine(“\t/? or /help \tDisplay this usage message”);
        }


        private static void GenerateXlsbXml(string viewName, string[] activityNames, string[] schemas)
        {
            //Create an writer for building the xlsb
            xlsbText = new StringBuilder();
            XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
            xmlWriterSettings.Indent = true;
            XmlWriter xlsbWriter = XmlWriter.Create(xlsbText, xmlWriterSettings);


            //Start building xml
            xlsbWriter.WriteStartDocument();
            xlsbWriter.WriteStartElement(BAMDefinition, BAMDefinitionNamespace);


            if (schemas.Length != activityNames.Length)
            {
                throw new ApplicationException(“The number of activity names and schemas don’t match.”);
            }


            Dictionary<string, string>[] checkpointIDsForSchemas = new Dictionary<string, string>[schemas.Length];
            string[] activityIDs = new string[schemas.Length];


            //Create the activities
            for (int i = 0; i < schemas.Length; i++)
            {
                Dictionary<string, string> checkpointIDs;
                string activityID;
                CreateActivity(xlsbWriter, schemas[i], activityNames[i],
                    out checkpointIDs, out activityID);
                checkpointIDsForSchemas[i] = checkpointIDs;
                activityIDs[i] = activityID;
            }


            //Now create the view
            xlsbWriter.WriteStartElement(View);
            xlsbWriter.WriteAttributeString(UCName, viewName);
            string viewID = Id + Guid.NewGuid().ToString(“N”);
            xlsbWriter.WriteAttributeString(Id, viewID);


            //Create Activity Views
            for (int i = 0; i < schemas.Length; i++)
            {
                CreateActivityView(xlsbWriter, activityNames[i],
                    checkpointIDsForSchemas[i], activityIDs[i]);
            }


            xlsbWriter.WriteEndElement(); //END View


            xlsbWriter.WriteStartElement(Extension);
            xlsbWriter.WriteElementString(OWC, OWCNamespace, “”);


            xlsbWriter.WriteEndElement(); //END Extension
            xlsbWriter.WriteEndElement(); //END BAMDefinition
            xlsbWriter.WriteEndDocument();
            xlsbWriter.Flush();
        }


        private static void CreateActivityView(XmlWriter xlsbWriter, string activityName,
            Dictionary<string, string> checkpointIDs, string activityID)
        {
            xlsbWriter.WriteStartElement(ActivityView);
            xlsbWriter.WriteAttributeString(UCName, View + activityName);
            xlsbWriter.WriteAttributeString(Id, Id + Guid.NewGuid().ToString(“N”));
            xlsbWriter.WriteAttributeString(ActivityRef, activityID);


            //Loop through the dictionary and create the Aliases
            foreach (string key in checkpointIDs.Keys)
            {
                xlsbWriter.WriteStartElement(Alias);
                xlsbWriter.WriteAttributeString(UCName, key);
                xlsbWriter.WriteAttributeString(Id, Id + Guid.NewGuid().ToString(“N”));
                xlsbWriter.WriteElementString(CheckpointRef, checkpointIDs[key]);
                xlsbWriter.WriteEndElement(); //END Alias  
            }


            xlsbWriter.WriteEndElement(); //END ActivityView 
        }


        private static void CreateActivity(XmlWriter xlsbWriter, string schema,
            string activityName, out Dictionary<string, string> checkpointIDs,
            out string activityID)
        {
            xlsbWriter.WriteStartElement(Activity);
            xlsbWriter.WriteAttributeString(UCName, activityName);
            activityID = Id + Guid.NewGuid().ToString(“N”);
            xlsbWriter.WriteAttributeString(Id, activityID);


            //Create a dictionary object to store the IDs in
            checkpointIDs = new Dictionary<string, string>();


            //Open the schema
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(schema);


            //The rules are


            XmlNodeList xmlNodeList = xmlDocument.SelectNodes(XpathToAttribute);


            //Loop through all the attributes and create the new xslb schema
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                string checkpointID = Id + Guid.NewGuid().ToString(“N”);
                checkpointIDs.Add(xmlNode.Attributes[LCName].Value, checkpointID);


                //Add the data type attributes
                if (xmlNode.OuterXml.Contains(XsdDateTime))
                {
                    xlsbWriter.WriteStartElement(Checkpoint);
                    xlsbWriter.WriteAttributeString(UCName, xmlNode.Attributes[LCName].Value);
                    xlsbWriter.WriteAttributeString(Id, checkpointID);


                    xlsbWriter.WriteAttributeString(DataType, SqlDateTime);


                    xlsbWriter.WriteEndElement(); //End Checkpoint
                }
                else if (xmlNode.OuterXml.Contains(XsdInteger))
                {
                    xlsbWriter.WriteStartElement(Checkpoint);
                    xlsbWriter.WriteAttributeString(UCName, xmlNode.Attributes[LCName].Value);
                    xlsbWriter.WriteAttributeString(Id, checkpointID);


                    xlsbWriter.WriteAttributeString(DataType, SqlInt);


                    xlsbWriter.WriteEndElement(); //End Checkpoint
                }
                else if (xmlNode.OuterXml.Contains(XsdDouble))
                {
                    xlsbWriter.WriteStartElement(Checkpoint);
                    xlsbWriter.WriteAttributeString(UCName, xmlNode.Attributes[LCName].Value);
                    xlsbWriter.WriteAttributeString(Id, checkpointID);


                    xlsbWriter.WriteAttributeString(DataType, SqlFloat);


                    xlsbWriter.WriteEndElement(); //End Checkpoint
                }
                else if (xmlNode.InnerXml.Contains(XsdString))
                {
                    xlsbWriter.WriteStartElement(Checkpoint);
                    xlsbWriter.WriteAttributeString(UCName, xmlNode.Attributes[LCName].Value);
                    xlsbWriter.WriteAttributeString(Id, checkpointID);


                    xlsbWriter.WriteAttributeString(DataType, SqlNvarchar);


                    if (xmlNode.InnerXml.Contains(Length))
                    {
                        xlsbWriter.WriteAttributeString(DataLength,
                            xmlNode.SelectSingleNode(XpathToLength).InnerText);
                    }
                    else if (xmlNode.InnerXml.Contains(MaxLength))
                    {
                        xlsbWriter.WriteAttributeString(DataLength,
                            xmlNode.SelectSingleNode(XpathToMaxLength).InnerText);
                    }
                    else
                    {
                        xlsbWriter.WriteAttributeString(DataLength, “255”);
                    }


                    xlsbWriter.WriteEndElement(); //End Checkpoint
                }
                else if (xmlNode.OuterXml.Contains(XsdString))
                {
                    xlsbWriter.WriteStartElement(Checkpoint);
                    xlsbWriter.WriteAttributeString(UCName, xmlNode.Attributes[LCName].Value);
                    xlsbWriter.WriteAttributeString(Id, checkpointID);


                    xlsbWriter.WriteAttributeString(DataType, SqlNvarchar);
                    xlsbWriter.WriteAttributeString(DataLength, “255”);


                    xlsbWriter.WriteEndElement(); //End Checkpoint
                }
                else
                {
                    Console.Write(“Unknown xsd datatype: ” + xmlNode.OuterXml + ” continuing to create xlsb.”);
                    checkpointIDs.Remove(xmlNode.Attributes[LCName].Value);
                }
            }
            xlsbWriter.WriteEndElement(); //End Activity
        }
    }
}


How to call example: BAMXlsbGenerator /x “C:\Projects\SynboogalooSamples\Test.xlsb” /v TestView /a [TestActivityA,TestActivityB] /s [C:\Projects\SynboogalooSamples\SampleTransactionA.xsd,C:\Projects\SynboogalooSamples\SampleTransactionB.xsd]


This saved me a lot of time all I needed to do now to finish setting up BAM was deploy the xlsb BAM definition using the BM.exe tool and use the Tracking Profile Editor to associate the message payload with the BAM activity definition about 5 minutes of drag n’ drop work. In the BAM Portal system testers can query transformed data and can even query the BAM tables if they want. They are able through BAM relationships to view the message contents each time it has been modified and logged to BAM.


I found this technique was a quick and simple way of empowering system testers to test BizTalk applications.


I should note another option for System Testing EAI solutions is to go with an implementation of FIT (Framework For Integration Testing)  here is a blog with more info.


Rob

MS BRE: Update to side-effects article

I posted an article on MS BRE side effects yesterday.   I had immediately to withdraw it for a few hours because I realised it was incomplete (and actually a little wrong) in one part.   Then I noticed I had swapped the legend text on the graph making it appear that caching made things slower, rather than faster!   I then discovered today that for the last three years I have been completely ignorant of the fact that you can drag and drop object constructors onto the ‘assert’ argument in the Rules Composer in order to expolit the built-in CreateObject function!   Big red face.   I have changed the offending paragraph where I moaned at Microsoft for not providing access to this functionality!   Given the number of times I have complained about the lack of comprehensive documentation for BizTalk and related technologies, it is ironic that Microsoft have documented this particular feature very cleary indeed, and even given a brief description of what happens behind the scenes!   I am suitably chastened.


The updated article remains at http://geekswithblogs.net/cyoung/articles/111169.aspx.   If anyone spots any other artefacts of my ignorance or inattention, do please let me know!

Naked Conversations

I recently finished Naked Conversations by Robert Scoble and Shel Israel.
I really enjoyed it for a few reasons. First, it was fun to watch reactions as folks caught the title out of the corner of their eye and the juicy thoughts became self-evident. But more importantly, it provides an excellent analysis of the blogging/business world intersection. It gave me a lot to think about on my own blog and our marketing position at Pluralsight, where blogging ads value to our business in many ways.
The main message I took aware from the book is the importance of being completely transparent and honest, or as Dave Winer likes to call it, come-as-you-are conversations. That, in a nutshell,is what makes you relevant. I think Steve Maine said it best on his blog:
One of the hard things about being a blogger in general is finding your voice. Writing in a public forum is very much a performative act; you subconsciously choose a persona to project to the world and evoke that person through your writing. The really great bloggers are the ones who can do this transparently. They write without feeling self-conscious, the literary equivalent of singing in the shower. They write as if their words have no effect on the world. Though that, their words acquire honesty and from honesty flows impact. I need to get myself back in that headspace.
I knew Robert (and his wife Maryam) — great people — before he was anybody in blogosphere, back when I was speaking at the early Fawcette shows (VBITS, VCDC, etc) and he was organizing the speakers. As I’ve watched his rise in blogosphere over the years, it’s clear to me that his untamed honesty and transparency is what people like about him, and ultimately what makes him relevant. I noticed those same traits in him during some of our early conference conversations many years ago. Maybe some people are justmade to blog and others aren’t. Sometime I wonder if I am — if I can really be transparent enough in public.
Hence, the name of the book, Naked Conversations. Expose yourself on your blog. Credibility and respect grow from these core principles, which are extremely valuable assets in any organization.

BizTalk 2006: Deploy the Policies with command line (BTSTask)

It is not so strightforward as it suppose to be.

Below are the bat files with comments:

 

@rem ———– Deploy.Policies.bat ———————————————
@call Settings.bat

 

@ECHO.
@ECHO.  Deploy Policies:
@ECHO.  ======================================================================
@ECHO.

 

@Time /T
@ECHO 1) Create the ResourceSpec.xml file.
@rem BTSTask ListApp  /ApplicationName:%ApplicationName%  /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase% /ResourceSpec:”%CurrentBuildPath%\ResourceSpec.xml

 

@Echo 2) Then edit it to remain only Policy recources.

 

@Echo 3) Export .xml to .msi
@rem BTSTask ExportApp /ApplicationName:%ApplicationName% /Package:”%CurrentBuildPath%\Policies.msi” /ResourceSpec:”%CurrentBuildPath%\ResourceSpec.xml”  /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@Echo 4) Import .msi (Before this Undeploy the existed policies, the /Overwrite doesn’t help! Or Stop the Application.)
BTSTask ImportApp /Package:”%CurrentBuildPath%\Policies.msi” /ApplicationName:%ApplicationName% /Overwrite  /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@Echo 5) Deploy policies one by one :((

 

@set PolicyName=VesselID
@set PolicyVersion=1.27
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@set PolicyName=CompanyID
@set PolicyVersion=1.0
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@set PolicyName=PortOfUnloadingID
@set PolicyVersion=1.0
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@set PolicyName=DocumentValidator
@set PolicyVersion=1.1
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 


@Time /T

 

@rem call RestartBTS.bat

 

pause

 


@rem ———– Settings.bat ———————————————
@set MyShortSolutionName=MyShortSolutionName
@Set SolutionName=MyCompany.Domain.%MyShortSolutionName%
@set SolutionDir=C:\Solutions\%MyShortSolutionName%
@SET CurrentBuildPath=%SolutionDir%\Builds\Current
@SET BizTalkServer=BTS-06V
@SET BizTalkDataBasesServer=BTS-06V
@SET BizTalkConfigurationDataBase=BizTalkMgmtDb
@Set ApplicationName=%MyShortSolutionName%.MyApp

 

Update on Visual Studio Team Edition for Database Professionals

My team has been using VS DBPro (DataDude) for a little over six months now and I thought I give you an update on how we use this tool in a "mixed" environment (SQL Management Studio & DataDude), what we like and what we'd like to see in future releases.

Using SQL Management Studio & Visual Studio Team Edition for Database Professionals Together

The first thing we found in our implementation of VS DBPro was that it took a serious effort (and some arm twisting) to overcome our bad development habit of opening SQL Management Studio for a "quick & dirty change" to a live database. Sometimes working in disconnected mode via VS DBPro it seemed as if we were taking a lot longer to complete a task than if we were working "connected" in SQL Management Studio. Given the small size of our team, we really needed to find a way to work quickly but safely during database development and using both tools together seems to have done the trick.

How This Works

We usually begin by "reverse engineering" an existing database using  the VS DBPro (DataDude) import wizard and then verify the results using the Schema Compare tool. Then we create a "sandbox" copy of the original database on our local workstations or on a shared test SQL instance by building and deploying the project. We may also use SQL Server Integration Services (SSIS) to copy representative data from the original database to our sandbox or we generate test data using the VS DBPro Data Generation tool. Once everything is setup, we load our source code into our Team Foundation Server instance for safekeeping.

We then use whichever toolset (SQL Management Studio or VS DBPro) makes the most sense to modify our sandbox database but we never (EVER) touch the live database for "quick & dirty" changes. We make our changes using SQL Management Studio, import them into our VS DBPro projects using the Schema Compare tool, then test our changes, build our projects and check in our changes to TFS just as you would in any other development language. Then and only then, do we use the VS DBPro's Schema Compare tool to build our incremental change scripts that we run against our production database.

This gives us the best of both worlds by allowing us to work "connected" to our sandbox database using SQL Management Studio but still have an easy way to test, build and store our SQL code using VS DBPro. I've found this to be a very workable solution until VS DBPro (DataDude) contains all the same functionality (table designers, query execution plans, database diagrams, etc.) that SQL Management Studio does. This also allows each DB developer to work with the tools he or she is most comfortable with and this is vital for developer productivity!

What We Really Like!

The four main features that we really love about VS DBPro (DataDude) are the Schema Import, Schema Compare & Data Compare, Source Control (in TFS) and the Initial Deployment experience. These four features really do change the way that database development is done and they alone make the product worthwhile to own. For details about these features be sure to read my previous posts!

The Future of VS DBPro (Publicly Available Information Only – I Promise)

Jeff Beehler recently announced the Team System Roadmap in his blog. Last month I had the incredible opportunity to sit down with several members of the Visual Studio team that is responsible for developing VS DBPro (Cameron Skinner, Robert Merriman, Mairead O'Donovan, Richard Waymire and others) to discuss this roadmap and I've never walked away from a meeting more enthusiastic about the future.

Visual Studio Team Edition for Database Professionals – Service Release 1

Gert Drapers, the team's Architect has written a great post about the first service release for VS DBPro (DataDude). This service release builds upon the RTM version by adding three new features; Database References, File Group Support and SQLCMD Variable Support. It also adds "official" support for SQL Server 2005 SP2 and Vista.

Visual Studio Team Edition for Database Professionals – Power Tools

The VS DBPro team has been very very busy and is working on a set of power tools to enhance the functionality of the Service Release 1 bits. The planned power tools include "Move Schema Refactoring", "Schema & Data Compare MSBuild Tasks", "Schema Object Dependency Tree", "SQL Static Code Analysis", "Support for Fully-Qualified Names" and "Schema Reporting" as well as a few others.

Visual Studio Orcas, Rosario & Beyond

If you read between the lines in Mairead O'Donovan's recent blog posts (1, 2) you can get a feel for what the team is looking at for future releases of VS DBPro. Obviously, the future of any product is not set in stone, but it's great to see how VS DBPro is evolving and growing into a full featured database development platform.

Share this post: Email it! | bookmark it! | digg it! | reddit!| kick it!

Windows Workflow Foundations Web Workflow Approval Starter Kit available now!!!

Hi All,
Software is undergoing a major revolution and windows workflow is definitely evolving in this process. Check out theWorkflow Foundations Web Workflow Approval Starter Kit which triggers a workflow from your asp.net application.
This starter kit is a Visual Studio 2005 project that demonstrates using Windows Workflow Foundation for simple task oriented workflow in an ASP.NET […]

BizTalk 2006: Deploy the Policies with command line (BTSTask)

It is not so strightforward as it suppose to be.

Below are the bat files with comments:

 

@rem ———– Deploy.Policies.bat ———————————————
@call Settings.bat

 

@ECHO.
@ECHO.  Deploy Policies:
@ECHO.  ======================================================================
@ECHO.

 

@Time /T
@ECHO 1) Create the ResourceSpec.xml file.
@rem BTSTask ListApp  /ApplicationName:%ApplicationName%  /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase% /ResourceSpec:”%CurrentBuildPath%\ResourceSpec.xml

 

@Echo 2) Then edit it to remain only Policy recources.

 

@Echo 3) Export .xml to .msi
@rem BTSTask ExportApp /ApplicationName:%ApplicationName% /Package:”%CurrentBuildPath%\Policies.msi” /ResourceSpec:”%CurrentBuildPath%\ResourceSpec.xml”  /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@Echo 4) Import .msi (Before this Undeploy the existed policies, the /Overwrite doesn’t help! Or Stop the Application.)
BTSTask ImportApp /Package:”%CurrentBuildPath%\Policies.msi” /ApplicationName:%ApplicationName% /Overwrite  /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@Echo 5) Deploy policies one by one :((

 

@set PolicyName=VesselID
@set PolicyVersion=1.27
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@set PolicyName=CompanyID
@set PolicyVersion=1.0
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@set PolicyName=PortOfUnloadingID
@set PolicyVersion=1.0
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 

@set PolicyName=DocumentValidator
@set PolicyVersion=1.1
BTSTask AddResource  /ApplicationName:%ApplicationName% /Type:System.BizTalk:Rules  /Overwrite /Name:%PolicyName% /Version:%PolicyVersion% /Server:%BizTalkDataBasesServer% /Database:%BizTalkConfigurationDataBase%

 


@Time /T

 

@rem call RestartBTS.bat

 

pause

 


@rem ———– Settings.bat ———————————————
@set MyShortSolutionName=MyShortSolutionName
@Set SolutionName=MyCompany.Domain.%MyShortSolutionName%
@set SolutionDir=C:\Solutions\%MyShortSolutionName%
@SET CurrentBuildPath=%SolutionDir%\Builds\Current
@SET BizTalkServer=BTS-06V
@SET BizTalkDataBasesServer=BTS-06V
@SET BizTalkConfigurationDataBase=BizTalkMgmtDb
@Set ApplicationName=%MyShortSolutionName%.MyApp

 

System Testing BizTalk Applications with BAM & Xlsb File Generation

In the past I have noticed that system testers find it difficult to test middleware applications such as those implemented using BizTalk. System testers generally don’t want to read BizTalk xml messages dumped out to disk, they like to be able to query for their test results via some form of GUI. Many are adept at writing SQL to return result sets containing the test data they want to analyze.


I came up with the idea of using BAM relationships between different activities within a single view to log before and after snapshots of BizTalk messages. So when messages were transformed by maps, orchestrations or the BRE system testers could test those transforms. You can then give system testers’ access to the BAM Portal Website where they could view and query these before and after snapshots and match the actuals against the expected results to pass or fail their tests.


This solution for system testing only works for certain scenarios’ with certain types of schemas as each message logged cannot contain repeating records if it is to be logged to BAM.


So what am I on about? Take a single record schema which validates an xml message like the one below as I said before this technique won’t work with messages which contain multiple records.


   <ns1:SampleTransaction TransactionID=”123456″ ProductName=”ABC” Amount=”1234.56″ Quantity=”24″ xmlns:ns1=”http://SynbogalooSamples/SampleTransaction/1.0.0.0″ />


Each time a map, orchestration or business rules were applied to a message I wanted to send messages to BAM so I was basically just logging messages to BAM each time the contents of the message changed. I used BAM relationships to associate the message before it was transformed to the message after it was transformed so the tester could assess whether the transformation worked.


OK this was all easy but very time consuming using the Excel add-in to create the xlsb files for each schema so I wrote a simple xlsb file generator. Note: For this code to work with schemas that have xsd types other than DateTime, Integer, Double and String you will need to add to the switch statement in the CreateActivity method.


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;


namespace BAMXslbGenerator
{
    class Program
    {
        private const string UCName = “Name”;
        private const string LCName = “name”;
        private const string View = “View”;
        private const string BAMDefinition = “BAMDefinition”;
        private const string BAMDefinitionNamespace = “
http://schemas.microsoft.com/BizTalkServer/2004/10/BAM“;
        private const string Extension = “Extension”;
        private const string OWC = “OWC”;
        private const string OWCNamespace = “urn:schemas-microsoft-com:office:excel”;
        private const string ActivityView = “ActivityView”;
        private const string ActivityRef = “ActivityRef”;
        private const string Activity = “Activity”;
        private const string Alias = “Alias”;
        private const string CheckpointRef = “CheckpointRef”;
        private const string Id = “ID”;
        private const string Checkpoint = “Checkpoint”;
        private const string XpathToAttribute =
            “(//*[local-name()=’element’])[last()]/*[local-name()=’complexType’]/*[local-name()=’attribute’]”;
        private const string DataType = “DataType”;
        private const string DataLength = “DataLength”;
        private const string Length = “length”;
        private const string MaxLength = “maxLength”;
        private const string XpathToLength = “*[local-name()=’simpleType’]/*[local-name()=’restriction’]/*[local-name()=’length’]/@value”;
        private const string XpathToMaxLength = “*[local-name()=’simpleType’]/*[local-name()=’restriction’]/*[local-name()=’maxLength’]/@value”;
        private const string SqlDateTime = “DATETIME”;
        private const string SqlNvarchar = “NVARCHAR”;
        private const string SqlInt = “INT”;
        private const string SqlFloat = “FLOAT”;
        private const string XsdDateTime = “xs:dateTime”;
        private const string XsdString = “xs:string”;
        private const string XsdInteger = “xs:int”;
        private const string XsdDouble = “xs:double”;


        private static StringBuilder xlsbText = null;


        static void Main(string[] args)
        {