Month: April 2012

Automatic retries using the Transient Fault Handling from Enterprise libraries (EntLib)


Hello,

I was reading about the Transient Fault Handling at http://msdn.microsoft.com/en-us/library/hh680901(v=pandp.50).aspx This is a block of the Enterprise Libraries which is part of the Enterprise Integration Pack for Windows Azure. I haven’t played much with Azure yet, but one part of the documentation took my attention:

When Should You Use the Transient Fault Handling Application Block?
…… (some explanation about when you are using Azure services) ……
You Are Using a Custom Service
If your application uses a custom service, it can still benefit from using the Transient Fault Handling Application Block. You can author a custom detection strategy for your service that encapsulates your knowledge of which transient exceptions may result from a service invocation. The Transient Fault Handling Application Block then provides you with the framework for defining retry policies and for wrapping your method calls so that the application block applies the retry logic.Source: http://msdn.microsoft.com/en-us/library/hh680901(v=pandp.50).aspx#sec10

So, I thought why do I have to write always the retry logic if this is already done ;-).

The problem

We want to write a generic retry mechanism for our application. Moreover we need to support some level of customization thru configuration files.

The solution
Simple let set up the Transient Fault Handling Block (from now on FHB). First of fall you will have to download the libraries, you could do it using NuGet – which by default adds also references to support Windows Azure -. You can remove the Windows Azure DLL if you’re not going to be using Windows Azure in your app.

The FHB lets you specify a error detection strategy as well as retry strategy when you construct the retry policy. Also, a Retry policy support the execution of Action, Funcdelegates or Actionfor async retries.

As part of the configuration process for FHB, it’s required to indicate which errors should be handled by FHB. A mechanism for doing this is by implementing the interface: ITransientErrorDetectionStrategy. In our sample, we only want to retry when a FileNotFoundException is thrown. Thus we have coded the FileSystemTransientErrorDetectionStrategy:

using System;
using System.IO;
using Microsoft.Practices.TransientFaultHandling;

namespace SampleConsoleApplication.TransientErrors.Strategies
{
    public class FileSystemTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy
    {
        #region ITransientErrorDetectionStrategy Members

        public bool IsTransient(Exception ex)
        {
            return ex is FileNotFoundException;
        }

        #endregion
    }
}

Certainly you could implement it by handling any particular exception.
Now we need to define a retry policy. This is done by specifying a retry strategy. The following code example configures a retry policy by providing a retry strategy incremental. Additionally in our sample service.DoSlowAndImportantTask will always fail, so the FHB will retry automatically based on the retry policy.

 private static void RetryPolityUsingCode(IUnityContainer container, IService service, OutputWriterService writer)
        {
            writer.WriteLine("Begin sample: RetryPolityUsingCode");
            // Define your retry strategy: retry 5 times, starting 1 second apart
            // and adding 2 seconds to the interval each retry.
            var retryStrategy = new Incremental(5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));

            // Define your retry policy using the retry strategy and the Windows Azure storage
            // transient fault detection strategy.
            var retryPolicy = new RetryPolicy(retryStrategy);

            try
            {
                // Do some work that may result in a transient fault.
                retryPolicy.ExecuteAction(service.DoSlowAndImportantTask);
            }
            catch (Exception exception)
            {
                // All the retries failed.
                writer.WriteLine("An Exception has been thrown:\n{0}", exception);
            }
            writer.WriteLine("End sample: RetryPolityUsingCode");
        }

Additionally it’s possible to specify the retry policy in the configuration file, for example:

<!--?xml version="1.0" encoding="utf-8" ?-->

<section name="RetryPolicyConfiguration" type="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.Configuration.RetryPolicyConfigurationSettings, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling" requirepermission="true"></section><section name="typeRegistrationProvidersConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.TypeRegistrationProvidersConfigurationSection, Microsoft.Practices.EnterpriseLibrary.Common"></section>

Please notice that there is a default Retry Strategy indicating that will use “Fixed Interval Retry Strategy”. Our C# code will ask for the RetryManager instance in order to retrieve the Retry Policy and then perform the task.

private static void RetryPolityUsingConfigFile(IUnityContainer container, IService service, OutputWriterService writer)
        {
            writer.WriteLine("Begin sample: RetryPolityUsingConfigFile");
            // Gets the current Retry Manager configuration
            var retryManager = EnterpriseLibraryContainer.Current.GetInstance();

            // Asks for the default Retry Policy. Keep on mind that it's possible to ask for an specific one.
            var retryPolicy = retryManager.GetRetryPolicy();
            try
            {
                // Do some work that may result in a transient fault.
                retryPolicy.ExecuteAction(service.DoSlowAndImportantTask);
            }
            catch (Exception exception)
            {
                // All the retries failed.
                writer.WriteLine("An Exception has been thrown:\n{0}", exception);
            }
            writer.WriteLine("End sample: RetryPolityUsingConfigFile");
        }

The Transient Fault Handling Block a simple and flexible alternative for a well-known task. A automatic retry system, moreover this supports configuration file, so we should be able to change the retry policy just by modifying our configuration file.

Here is an screen shot of the app, which automatically retries calling our mischievous method.

Transient Fault Handling Tries Output Capture

As usual the code sample is at https://github.com/hmadrigal/playground-dotnet/tree/master/MsEntLib.TransientErrorHandling

Multiple configuration files per environment


Hello,

Today I had the chance to perform a quick research about a classic problem. If have different settings for development, testing, staging and production. So, we usually merge or lost settings of the configuration files. Visual Studio 2008 have already resolved the problem (at least in web applications) by allowing the user to create different web.config files and applying XSLT to generate the final configuration file. Today I’ll propose the same solution, but for desktop Apps, and hopefully you could apply this solution to any XML file.

Just in case you’re one of those who want to download a sample, you coudl get it at https://github.com/hmadrigal/playground-dotnet/tree/master/MsDotNet.MultipleConfigurationFile

The Problem:

We have a configuration file ( .config or any xml document), and we want to have different settings per environment (development, testing, staging and production). Moreover we want to automate this process, so we don’t have to write the settings manually.

Remarks

  • It’s good to know basics of MSBuild and how to modify project.
  • It’s good to know about XML, XPath and XSLT

The solution

Create one configuration per environment 

Let’s start by creating configuration settings for each environment where you need custom settings. You could do it by click on “Configuration Manager…“. For example I’ve created the environments that we’re gonna use on this example.

Image

Now, add a configuration file (in our case app.config) and also add one config file per environment. Please note that the configuration file app.config contains most of the final content, and the other configuration files will hold only XSLT expressions to modify the original. As a convention usually the file names are: app.$(environment).config. The following image illustrates the configuration files:

Image

More in detail app.config, contains three simple settings:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="EnvironmentName" value="Debug" />
    <add key="ApplicationDatabase" value="Data Source=DevelopmentServer\SQLEXPRESS;Initial Catalog=DevelopmentDatabase;Integrated Security=True;" />
    <add key="ServerSharedPath" value="\\127.0.0.1" />
  </appSettings>
</configuration>

Set up your project to use a XslTransform task once the compilation is done

Now you will have to edit the project file using a text editor. VS project files are XML, these normally are read by VS and see the project structure. However there are tasks that only can be customized by editing manually the XML file. You can modify the xml of a project within Visual Studio by using right (secondary) click on the project from the Solution Explorer. Then, click on “Unload project”, and once again right click and now select “Edit project …”. Now, you should be able to see the XML associated to the selected project.

You’ll be adding two targets (or if modifying if any of them is already in place). The following code:

<Target Name="ApplySpecificConfiguration" Condition="Exists('App.$(Configuration).config')">
    <XslTransformation XmlInputPaths="App.config" XslInputPath="App.$(Configuration).config" OutputPaths="$(OutputPath)$(RootNamespace).$(OutputType).config" />
    <Copy SourceFiles="$(OutputPath)$(RootNamespace).$(OutputType).config" DestinationFiles="$(OutputPath)$(RootNamespace).vshost.$(OutputType).config" />
  </Target>
  <Target Name="AfterBuild">
    <CallTarget Targets="ApplySpecificConfiguration" />
  </Target>

The previous XML portion Adds a custom task called and it uses MSBuild variables to determine the name of the configuration file, our example is using a Console App, thus we need to create a copy of the config file but with vshost.config extension, so we added a copy task.  The second thing we’ve added is a call to the task we’ve just created, this call is added into the AfterBuild Target. The AfterBuild is invoked by MSBuild automatically when the build process has finished.

Transform your app.config with XSLT

On this section, we’re gonna write the content for each configuration. This will let us custom XML porting into the final configuration file. As example, here is the XML for the production transformation:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>

  <!-- Nodes to be replaces -->
  <xsl:template match="/configuration/appSettings/add[@key='EnvironmentName']">
    <add key="EnvironmentName" value="Production" />
  </xsl:template>
  <xsl:template match="/configuration/appSettings/add[@key='ApplicationDatabase']">
    <add key="ApplicationDatabase" value="Data Source=PRODUCTION\SQLEXPRESS;Initial Catalog=ProductionDatabase;Integrated Security=True;" />
  </xsl:template>
  <xsl:template match="/configuration/appSettings/add[@key='ServerSharedPath']">
    <add key="ServerSharedPath" value="\\PRODUCTION" />
  </xsl:template>

  <!-- Copy all the remaining nodes -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

I know XSLT might sound intimidating at first, but it’s kinda easy.BTW XSLT uses XPath, so if you want to know the basics of them, please check out w3c school for a quick reference. XPath at http://www.w3schools.com/xpath/xpath_examples.asp and XSLT at http://www.w3schools.com/xsl/xsl_transformation.asp

To put it in a nutshell, our XSLT is detecting specifically three attributes (by its name and location into the XML) and replacing them with a custom value. All the remaining nodes are kept into the final XML.

Let run our sample

Just to make it work I’ve coded two classes, one that defines the constant name of the settings and a main class which print values from the configuration file.

using System;
using System.Configuration;

namespace MultipleConfigurationFilesSample
{
    public static class ApplicationConstants
    {
        public class AppSettings
        {
            public const string ServerSharedPath = @"ServerSharedPath";
            public const string EnvironmentName = @"EnvironmentName";
            public const string ApplicationDatabase = @"ApplicationDatabase";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var environment = ConfigurationManager.AppSettings[ApplicationConstants.AppSettings.EnvironmentName];
            var serverSharedPath = ConfigurationManager.AppSettings[ApplicationConstants.AppSettings.ServerSharedPath];
            Console.WriteLine(@"Environment: {0} ServerSharedPath:{1}", environment, serverSharedPath);
            Console.ReadKey();
        }
    }
}

Now I have run the application twice, but using different configurations. The first was using development and I got the following output:

Image

The second was using Production configuration, and it produces the following output:

Image

As you can see, the selected environment is determining the settings into the resultant configuration file.

As usual the source code can be fond at https://github.com/hmadrigal/playground-dotnet/tree/master/MsDotNet.MultipleConfigurationFile

References:
References: http://litemedia.info/transforming-an-app-config-file

Best regards,
Herber