Infosys Microsoft Alliance and Solutions blog

« September 2006 | Main | November 2006 »

October 30, 2006

BizTalk 2004 SP2

Working with BizTalk 2004 ! Here's SP2 for you. Published on 25 Oct 2006. You can download it from here. Related resource is the list of fixes in this SP release. Check that out here.

October 27, 2006

BizTalk 2006 Documentation

Keep a watch on this link (add it to your favorities). Latest BizTalk 2006 documentation gets published on it. The latest available is published on 23 Oct 2006.

BizTalk - String manipulation using Business Rules Engine

Some time back while working on a project we had requirement to do input data cleansing. The input would be a known XML format and could come from know sources. However each source could have used a different string representation than a standard one and hence it was required to fix this prior to working with the XML. For example we would want the color to be represented as "green", while the input could contain GREEN, GRN, grn etc.

There were some common conversions which were to be done for any source. However some conversions were only to be done for specific sources and additionally support was required to add new sources at any time without rebuilding the application. We discussed and decided that Mapping won't work since, one we needed a generic string replacement as against specific XML node manipulation and two we wanted dynamic addition of sources.

What follows is a discussion of the solution that we implemented. I would like to acknowledge the support from my colleague Jitendra Pal Thethi in coming up with this solution and the code base. Considering the different string manipulations required for each source and ability to dynamically add new sources, we decided to use Business Rules Engine (BRE) along with a custom .net component that do the actual execution. Following are some sample rules that we built for this functionality. The first one was to handle the generic case i.e. the rule that will run for all sources.

IF
    Conditions
        SourceName is not equal to ""
THEN
    Actions
        Replace GRN with green
        Replace string1 with string2
        Replace string3 with string4

For a specific source, the Conditions part was altered to as below, while the actions were written in similar manner. Only the values of the strings to replace were altered as required.

IF
    Conditions
        SourceName is equal to SourceA

At any given time a new rule could be added for a new source as required and when deployed, the new policy will be picked up and be used and thus allowly easy dynamic addition of new source handling. 

The final rule to trigger the actual string replacement was something like this

IF
    Conditions
        1 is equal to 1
THEN
    Perform ReplaceAll

The condition of 1 equal to 1 forced the rule to be always executed. This can be optimized by looking up the count of strings identified for replacing. If the count is 0, we can skip executing any further code. However since BRE loads all facts and checks them upfront to build the agenda, if we did something like StringCollection.Count, it would return 0 always since at the start of execution there aren't any strings yet added. This means that even if we later add strings to the collection, the rule will still not fire since it never got added to the agenda. This can be easily addressed by doing an Assert to tell BRE that a fact has been updated. However this is also easily implemented as part of our custom .net component so we left the rule simple.

As I mentioned earlier, we also had written a custom .net component to do the actual execution. The SourceName, Replace and ReplaceAll as used in rules above are vocabularies built over this class. To capture the string values that represent the source and destination, we created a custom class as below

    [Serializable]
    public class ReplaceInfo
    {
        private string sourceString;

        public string Source
        {
            get { return sourceString; }
            set { sourceString = value; }
        }

        private string destString;

        public string Target
        {
            get { return destString; }
            set { destString = value; }
        }
    }

This class was then used in our Entity class that had a List collection to store the ReplaceInfo type. Part of this Entity class is shown below. Other than this it also had a private XmlDocument member that represented the input XML message.

    [Serializable]
    public class Entity
    {
        private XmlDocument doc;

        public XmlDocument MessageData
        {
            get { return doc; }
            set { doc = value; }
        }

        private string providerField;

        public string SourceProvider
        {
            get { return providerField; }
            set { providerField = value; }
        }

        private List<ReplaceInfo> listField = new List<ReplaceInfo>();

        public List<ReplaceInfo> ReplaceStringCollection
        {
            get { return listField; }
        }
    ...
    ...
    ...
    }

The SourceProvider property of the Entity class, as shown above, returned the name of the current Source and it was on the get accessor of this the SourceName vocabulary was built.  We then need a class to execute the strings stored in the Entity class and also add strings to be replaced to the list collection in the class. This was done using another class as below

    [Serializable]
    public class RuleExecutor
    {

        public void AddString(string strFrom, string strTo)
        {
            ReplaceInfo r = new ReplaceInfo();
            r.Source = strFrom;
            r.Target = strTo;
            entity.ReplaceStringCollection.Add(r);
        }

        public void ReplaceAll()
        {
            StringBuilder sb = new StringBuilder(entity.MessageData.InnerXml);

            foreach (ReplaceInfo rInfo in entity.ReplaceStringCollection)
            {
                sb.Replace(rInfo.Source, rInfo.Target);
            }
           
            //done with the string replacements.. put the modified XML back in the
            //property variable from where the orchestration will pick it up
            entity.MessageData.InnerXml = sb.ToString();
        }
    ...
    ...
    ...
    }

The AddString method of this class is set as the Replace vocabular that is used as part of the Actions of the rules mentioned earlier and the ReplaceAll method is set as the ReplaceAll vocabulary. Since BRE offers setting a more user friendly display name, we set the "AddString" .net class method as "Replace {0} with {1}", as seen in the rule snipper earlier.

This way we built an easy mechanism to manipulate strings and also had the ability to add more sources at run time. To test the rules we also built fact creator by implementing the IFactCreator interface and providing implementations for CreateFacts and GetFactTypes methods. 

October 24, 2006

Cross Thread UI control access

We all know that when working with Winform applications and threads, we need to be careful about accessing the UI controls. These controls are meant to be accessed only on the thread that built them, which in this case is the primary application thread.

In multithreaded applications, when additional threads are used to perform background jobs to ensure that the UI remains responsive, one has to be careful about updating the controls on the form. There are articles already, that talk about how to address this problem. Check here.

With .net framework 2.0 and VS2005, there are improvements that help work with this issue easily. One of the improvements is the more user friendly exception display that occurs when running the application in debug mode. If your code does cross thread access, it will result in a error message like the following

CrossThreadError.jpg

.Net 2.0 also introduced a new class called BackgroundWorker class. This class has support for doing a lengthy work in background and then posting the completion event to the primary thread. This way in the completion event handler, you can safely update the UI controls without worry of cross thread access.

The article that I refered to earlier, talks about possibilities of using Invoke or BeginInvoke, where we know that the BeginInvoke method does the same work, but asynchronously. One can additionally call this.InvokeRequired to check if we really need to make the Invoke call or the execution is already on the primary thread. With my background in having done lot of Windows programming and working with DispatchMessage and TranslateMessage APIs and also writing message handlers in WndProc, I knew that when BeginInvoke or Invoke is called, it is bound to be doing a PostMessage to the primary thread, but I wanted to really how this was being done.

Needless to say that Lutz Reoder's .Net Reflector came in handy. Without going into line by line details of the internal workings, I will capture the key points here and you are welcome to drill down deeper into this on your own.

The Invoke/BeginInvoke methods support two overloads. One, that takes only a delegate (for callback and actual execution of UI updation logic) and another that takes the delegate as well an object array that you may want to pass to the delegate. The definition of the delegate is really upto the programmer based on the logic required to update the UI controls. The single parameter overloads call the second overload internally by passing null for the second parameter. For example

public IAsyncResult BeginInvoke(Delegate method)
{
      return this.BeginInvoke(method, null);
}

These methods then internally use the MultithreadSafeCallScope internal private class to ensure that the further execution happens in a thread safe way. Eventually the call is made to the control's MarshaledInvoke private method. The method signature is

private object MarshaledInvoke(Control caller, Delegate method, object[] args, bool synchronous)

The Delegate and the object array parameters are the ones that have been sent from the calling code. The synchronous boolean is set based on if the call is make from Invoke (true) or BeginInvoke (false). The key to this message execution is the check on the current executing thread ID and the thread ID of the control's creation thread. The calls are made using another internal class called SafeNativeMethods. The method calls of interest here are

1. SafeNativeMethods.GetCurrentThreadID : This is a method found in kernel32.dll and as the name suggests, gets the ID of the thread on which the code is currently executing.

2. SafeNativeMethods.GetWindowThreadProcessID : This is a method found in User32.dll and is used to find the thread that created the Window (the Winform in current context) and optionally the process ID also.

You can check Windows SDK documentation for more details on these methods.

The comparison of the thread IDs returned by these methods essentially decides the fate of further execution. If the two values are equal, this means that the current call is already happening on a thread that created the UI and hence can be used to safely modify the UI controls, else, it means that this is a different thread.

A new ThreadMethodEntry is created with the parameters passed to the Invoke/BeginInvoke methods and also capturing the current execution context. This entry is added to the ThreadCallbackList. If we are already on the right thread, a call is made to executed the delegate that the calling code had passed, else, a call to UnSafeNativeMethods.PostMessage is done to post the message to the thread's queue. People with windows programming experience will know the significance of PostMessage or SendMessage Windows APIs.

Finally, if the call came in via Invoke method, i.e. the synchronous parameter is true, the code waits for completion of execution using WaitForWaitHandle, else if called via BeginInvoke, the call completes and the IAsynchResult is returned to the calling code. Since the intention is to update the UI controls via the methods registered using the delegate, most likely you aren't bothered about the IAsynchResult result and in time the call to the delegate will complete, when the primary threads gets around to process its message queue.

To conclude, following are two ways to use the Invoke/BeginInvoke methods. In the code below, I have shown using BeginInvoke, but the same can be replaced with Invoke to get synchronous execution.

Option 1 : Using this.InvokeRequired. This is done when the same method updates the UI controls so need to ensure if we are on the right thread.

        private void btnProcess_Click(object sender, EventArgs e)
        {
            //queue the work for thread processing
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
        }

        private void ThreadProc(object stateInfo)
        {
            //do some thread specific work here..
            //simulate long work by sleeping for 2 secs
            Thread.Sleep(2000);

            //done. Update UI
            SetTextOnControls()
        }

        private delegate void UICallerDelegate();

        private void SetTextOnControls()
        {
            if (this.InvokeRequired)
            {
                UICallerDelegate dlg = new UICallerDelegate(SetTextOnControls);
                BeginInvoke(dlg, null);
            }
            else
            {
                label1.Text = DateTime.Now.ToShortTimeString();
                label2.Text = DateTime.Now.ToShortTimeString();
                button1.Text = DateTime.Now.ToShortTimeString();
                textBox1.Text = DateTime.Now.ToShortTimeString();
            }
        }

Option 2 : Without using this.InvokeRequired.

        private void btnProcess_Click(object sender, EventArgs e)
        {
            //queue the work for thread processing
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
        }

        private void ThreadProc(object stateInfo)
        {
            //do some thread specific work here..
            //simulate long work by sleeping for 2 secs
            Thread.Sleep(2000);

            //done. Update UI
            UICallerDelegate dlg = new UICallerDelegate(SetTextOnControls);
            BeginInvoke(dlg, null);
        }

        private delegate void UICallerDelegate();

        private void SetTextOnControls()
        {
            label1.Text = DateTime.Now.ToShortTimeString();
            label2.Text = DateTime.Now.ToShortTimeString();
            button1.Text = DateTime.Now.ToShortTimeString();
            textBox1.Text = DateTime.Now.ToShortTimeString();
        }

October 19, 2006

BizTalk 2006 - 2004 Performance Comparison

Recently we had concluded doing a performance comparison between the latest BizTalk Server 2006 and the previous 2004 version. Needless to say that the results were in favor of BizTalk Server 2006 running on SQL Server 2005.

We were amazed at the percentage performance improvement that this new combination delivered in certain specific scenarios. For more details check here.

October 18, 2006

Settings in .net Fwk 2.0

Working with Configuration files in .net fwk 1.1 was additionally supported by the Configuration block available as part of Enterprise Library (EL). With the release of .net fwk 2.0 and the introduction of System.Configuration subsystem, this is now becoming the way to work with configuration files. Hence EL 2.0 doesn't include a new Configuration block any more. Check this.

Working with System.Configuration via the Settings is quite simple with Visual Studio (VS) 2005. Check this article in case you need to know how to go about using it.

What I am going to talk about here is more in terms of how to bring in settings from libraries that you use in your code and merge with main application settings. Needless to say that any application one writes, will be using quite a few library components and without properly integrating their settings with the main application, things won't work as expected at runtime.

Lets build a sample application so as to help explain things properly. From VS2005, create a new Windows Application project. I called it SettingsDemo. Then I added another project to this same solution. The type of this was Class Library project and I called it CustomLibrary. Following this I added reference to the CustomLibrary project in my SettingsDemo project so that I could start using the library component. Adding project reference ensures build dependency and hence is better than directly adding reference to CustomLibrary.dll.

You will notice that the CustomLibrary component doesn't has a settings file under Properties. You can add one by either doing a "Add New Item" and select Settings file OR, you can go to Project properties and select Settings tab. It will prompt you to create a new settings file.

Once done, you can double click Settings.settings from Solution explorer, if not already open and start adding your own configuration values. For simplicity sake, I added two entries here String1 and String2 with Application scope and gave them some default values. I then added two public methods to the CustomControl to return the strings I just added. Sample code is as below

public string FirstMessage
{
    get { return Settings.Default.String1; }
}

In order to use Settings in code, you will have to add using CustomLibrary.Properties; to the top. Go ahead and build the solution. Next I added two buttons on the Form1 in the SettingsDemo windows application project. In the Click event handlers for these buttons, I instantiated the CustomLibrary component and make a call to the public method. Sample code is as below

private void button1_Click(object sender, EventArgs e)
{
    CustomLibrary.MyClass obj = new CustomLibrary.MyClass();
    MessageBox.Show(obj.FirstMessage);
}

If you have been implementing alongside, you can build now and run the application. On the form that comes up, hit a button and you will see a message box display the string value added to the Settings.settings of CustomLibrary previously. So far so good, but the point of using Setting is the ability to change at run time. These values are expected to be part of the configuration file. However if you were to check the SettingsDemo\bin\debug folder, you won't find any.

If you have been implementing alongside, you can build now and run the application. On the form that comes up, hit a button and you will see a message box display the string value added to the of previously. So far so good, but the point of using Setting is the ability to change at run time. These values are expected to be part of the configuration file. However if you were to check the folder, you won't find any.

So how did the code work? If you would go back to the solution explorer and navigate to Settings.designer.cs in the CustomLibrary project, and open it, you will notice that this file has two public methods and their names are same as the names we used in the Settings. Incidently, this is also the reason why we were able to access these via the Settings.Default.String1; call shown earlier. You will also notice that there is DefaultSettingValueAttribute and it has the value we entered for the setting in question earlier. The code (snapshot) in Settings.designer.cs would look something like below

[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()][global::System.Configuration.DefaultSettingValueAttribute("This is string1")]
public string String1 {
    get {
        return ((string)(this["String1"]));
    }
}

The ApplicationScopedSettingAttribute was added since we marked the setting as Application scope. If it is user scope, the attribute used will be UserScopedSettingAttribute. The DebuggerNonUserCodeAttribute is to mark this code as non-user code. In this case, this is wizard generated code. The final one DefaultSettingValueAttribute is the one that ensures that even when there isn't a configuration file present, there will still be a default value returned and prevent exceptions during code execution.

The was added since we marked the setting as Application scope. If it is user scope, the attribute used will be . The is to mark this code as non-user code. In this case, this is wizard generated code. The final one is the one that ensures that even when there isn't a configuration file present, there will still be a default value returned and prevent exceptions during code execution.

If you are wondering that how do I change these values at runtime, since I can't be expected to edit this Settings.designer.cs file and rebuild everytime, you need to check out the app.config file in CustomLibrary project. This is where the entries are added and it is this file that you will modify at runtime to get the new values for your configurations. In my case the app.config file looks like below

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="applicationSettings"  type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="CustomLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <applicationSettings>
    <CustomLibrary.Properties.Settings>
      <setting name="String1" serializeAs="String">
        <value>This is string1</value>
      </setting>
      <setting name="String2" serializeAs="String">
        <value>This is string2</value>
      </setting>
    </CustomLibrary.Properties.Settings>
  </applicationSettings>
</configuration>

When you build, you will also see CustomLibrary.dll.config getting created in CustomLibrary\bin\Debug folder. However this isn't copied to the SettingsDemo\bin\Debug folder and hence you aren't able to change the values at runtime. However don't get carried way and copy this file to SettingsDemo\bin\Debug for that doesn't help. You can give it a quick try. Copy the CustomLibrary.dll.config to this folder, edit it and make changes to the value of String1 or String2 setting and re-run the application. It will continue to show the old values.

This is where the merging comes into picture and for this we need to access the app.config file for SettingsDemo application. In case you don't see this file in solution explorer, you can add a new one via "Add New Item" and select Application Configuration file. It is in this file that we need to copy the entries done in app.config of CustomLibrary component. To easily follow how to make these entries, let first add a Setting to SettingsDemo project also. This will ensure that we already have entries in the App.config file for SettingsDemo project. I added a new setting called LocalString.

To this file we will add the CustomLibrary settings also. If you see the App.config file, you will see the <applicationSettings> section. It is in this section that the settings from CustomLibrary will be copied. You will also notice a subgroup <SettingsDemo.Properties.Settings> and likewise we will copy the entire section from CustomLibrary's app.config file to this. Additionally, to be able to read this newely added section, we need to make an entry to the <configSections><sectionGroup> group. Currently it is having an entry like <section name="SettingsDemo.Properties.Settings" ... and we need to add CustomLibrary.Properties.Settings. After modifications the file will look like as below (the bold faced text shows the additions done)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="SettingsDemo.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      <section name="CustomLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <applicationSettings>
    <SettingsDemo.Properties.Settings>
      <setting name="LocalString" serializeAs="String">
        <value>This is local string</value>
      </setting>
    </SettingsDemo.Properties.Settings>
    <CustomLibrary.Properties.Settings>
      <setting name="String1" serializeAs="String"
>
        <value>This is string1</value
>
      </setting
>
      <setting name="String2" serializeAs="String"
>
        <value>This is string2</value
>
      </setting
>
    </CustomLibrary.Properties.Settings
>
  </applicationSettings>
</configuration>

With this, now buid the application. Go to the SettingsDemo\bin\debug folder and open and edit the SettingsDemo.exe.config to make changes to the values of individual settings. Save and close the file and then run the SettingsDemo.exe from this folder. When you invoke the buttons, you will see the new values being displayed.

With this, now buid the application. Go to the folder and open and edit the to make changes to the values of individual settings. Save and close the file and then run the from this folder. When you invoke the buttons, you will see the new values being displayed.

Note that after making changes to the SettingsDemo.exe.config, if you run from VS, it might end up overwritting your modified file, so it is best to directly run the EXE as I mentioned above.

Hope this helps. Get back to me in case of any questions.

October 17, 2006

Chris Brumme's weblog

Reading blogs of Chris were always a treat. It was hence like a personal loss when he seemed to have taken a long vacation from blogging. Recently, after a gap of more than 2 years, I saw an update and hopefully we will get to read more interesting things from him, like before.

October 16, 2006

BizTalk - Which RuleSetDeploymentDriver class to use?

Recently when trying to work programmatically with BizTalk rules, I noticed that the RuleSetDeploymentDriver class appears twice, once in the Microsoft.RuleEngine namespace and once in Microsoft.BizTalk.RuleEngineExtensions. Not able to figure out what to use where, I dropped a mail to Sreedhar. In his response he indicated that when calling the policies from a generic Winform application, one should use Microsoft.RuleEngine.RuleSetDeploymentDriver and when working with BizTalk, one should use Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver.

He said that he will update the documentation and I did notice a new blog on his site about this.

October 12, 2006

Custom Control's Default Property Value

Recently a person put forth a query that he has written a custom control, overridden from an existing control, and using it in a Winform application. He was assigning some default values for some of the properties in the control's constructor. First time he added that control to the Winform, it showed the default values properly, however when we edited the custom control, recompiled and ran the Winform application again, the control instance on the form still showed the old value.

What was he doing wrong? For some of the properties of the base control like Text, this was working but for some like BackColor, this wasn't.

Looking at the typical Winform code, you will see that in the Form's .cs code, a call being made to InitializeComponent in the constructor. If you are working with .net fwk 2.0, the implementation of this function will be in the form's designer.cs file. A quick analysis of this method reveals the reason for the above stated problem.

All the controls being used on the forms are first instantiated and then further in code, each control's properties and their assigned values are listed. For example

this.MyCustomControl1 = new MyCustomControl();

//
// MyCustomControl1
//
this.MyControlControl1.BackColor = System.Drawing.Color.Blue;

This means that when the form is loaded, it will first call the control's constructor and then assign the value of the BackColor property to a value of Blue. This code was generated since this control had a property BackColor and it was being initialized to Blue in the constructor. So if we can get this assignement to a value of Blue removed from the form's InitializeComponent method, when we change the value in the control's constructor, and rebuild it, it should work fine.

This is handled by using an attribute with the property. The property that you don't want to get persisted to the designer, should be tagged with the following attribute

[System.ComponentModel.DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

There are other options for the DesignerSerializationVisibility enum. You can check the documentation for details on the values. Marking this as hidden, ensures that when the control is added to a form, the particular property value isn't serialized in the InitializeComponent method. Now you can go ahead and easily make changes to the property values in the control's constructor and everytime you run the application, the value being assigned in the constructor is what will get used.

Hope this helps. If you have questions, drop me a mail

Subscribe to this blog's feed

Follow us on

Blogger Profiles

Infosys on Twitter