Wednesday, September 3, 2008

Configuring Biztalk 2006 Rule Engine Update Service - the hardcore way

Why to do it this way one may ask? Because in my experience the nice way doesn't work in about 30% of all cases. Let me say that Biztalk configuration tool is not the most reliable and robust piece of software in the world. Great if it works for you for 100%, if not, continue reading ...

1. "Install"

Use service controller command line utility to create the service:

sc create RuleEngineUpdateService binPath= "C:\Program Files\Common Files\Microsoft BizTalk\RuleEngineUpdateService.exe" DisplayName= "Rule Engine Update Service"

Configure service account and run mode.

2. Configure

There are few options to do it. I provide the reflected code at the bottom of this entry to understand the options. I liked pretty much the option of using a stand-alone config file for this. From the code it is obvious that the simplest solution will be a SingleTagSection to configure. Update the bellow with your specific db server and db names and copy into the C:\Program Files\Common Files\Microsoft BizTalk\ folder named as RuleEngineUpdateService.exe.config.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="Microsoft.RuleEngine" type="System.Configuration.SingleTagSectionHandler, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </configSections>
    <Microsoft.RuleEngine DatabaseName="YourBizTalkRuleEngineDb" DatabaseServer="YourRulesDBServer" />
</configuration>

This is it for the most basic setup (which can be 99% of all cases though). See bellow for all possible values you might need to configure. One of the solutions would be to just copy chunk of registry from working box to the target, or instead of registry still add values as attributes in the above shown config file.

3. Understand the internals

The registry path for keys:

private const string registryPath = @"Software\Microsoft\BusinessRules\3.0";

The option for the config file follows from this (Configuration class in the Microsoft.RuleEngine namespace and dll)

static Configuration()
{
    m_configValues = ConfigurationManager.GetSection("Microsoft.RuleEngine") as IDictionary;
}
Getting string key/value:
private static string GetString(string key, string defaultValue)
{
    if ((m_configValues != null) && m_configValues.Contains(key))
    {
        return (string) m_configValues[key];
    }
    bool flag = IntPtr.Size == 8;
    RegistryKey key2 = Registry.LocalMachine.OpenSubKey(flag ? @"Software\Wow6432Node\Microsoft\BusinessRules\3.0" : @"Software\Microsoft\BusinessRules\3.0");
    if (key2 != null)
    {
        object obj2 = key2.GetValue(key);
        key2.Close();
        if (obj2 != null)
        {
            return (string) obj2;
        }
    }
    return defaultValue;
}
Same for int:
private static int GetInt32(string key, int defaultValue)
{
    if ((m_configValues != null) && m_configValues.Contains(key))
    {
        return int.Parse((string) m_configValues[key], CultureInfo.CurrentCulture);
    }
    bool flag = IntPtr.Size == 8;
    RegistryKey key2 = Registry.LocalMachine.OpenSubKey(flag ? @"Software\Wow6432Node\Microsoft\BusinessRules\3.0" : @"Software\Microsoft\BusinessRules\3.0");
    if (key2 != null)
    {
        object obj2 = key2.GetValue(key);
        key2.Close();
        if (obj2 != null)
        {
            return (int) obj2;
        }
    }
    return defaultValue;
}
What to keep in mind for all possible options to configure (fields of Configuration class, some fields are names of keys, some are default values):

// Fields
 private const string analyzerClass = "AnalyzerClass";
private const string analyzerClassDefault = "";
private const string analyzerDll = "AnalyzerAssembly";
private const string analyzerDllDefault = "";
private const string cacheCount = "CacheEntries";
private const int cacheCountDefault = 0x20;
private const string cachePruneInterval = "CachePruneInterval";
private const int cachePruneIntervalDefault = 60;
private const string cacheTime = "CacheTimeout";
private const int cacheTimeDefault = 0xe10;
private const string configurationFileKey = "Microsoft.RuleEngine";
private const string databaseName = "DatabaseName";
private const string databaseServer = "DatabaseServer";
private const string dataConnectionMaximumRows = "DataConnectionMaximumRows";
private const int dataConnectionMaximumRowsDefault = 0x186a0;
private const string deploymentDriverClass = "DeploymentDriverClass";
private const string deploymentDriverClassDefault = "Microsoft.RuleEngine.RuleSetDeploymentDriver";
private const string deploymentDriverDll = "DeploymentDriverAssembly";
private const string deploymentDriverDllDefault = "Microsoft.RuleEngine";
private static IDictionary m_configValues;
private const string PolicyFetchHandlerAssembly = "PolicyFetchErrorHandlerAssembly";
private const string PolicyFetchHandlerAssemblyDefault = "";
private const string PolicyFetchHandlerClass = "PolicyFetchErrorHandlerClass";
private const string PolicyFetchHandlerClassDefault = "";
private const string pubSubAdapterClass = "PubSubAdapterClass";
private const string pubSubAdapterClassDefault = "Microsoft.RuleEngine.PubSubAdapter";
private const string pubSubAdapterDll = "PubSubAdapterAssembly";
private const string pubSubAdapterDllDefault = "Microsoft.RuleEngine";
private const string registryPath = @"Software\Microsoft\BusinessRules\3.0";
private const string registryPath64 = @"Software\Wow6432Node\Microsoft\BusinessRules\3.0";
private const string remoteUpdatePollingInterval = "PollingInterval";
private const int remoteUpdatePollingIntervalDefault = 60;
private const string remoteUpdateServiceMachine = "UpdateServiceHost";
private const string remoteUpdateServiceMachineDefault = "localhost";
private const string remoteUpdateServiceName = "UpdateServiceName";
private const string remoteUpdateServiceNameDefault = "RemoteUpdateService";
private const string remoteUpdateServicePort = "UpdateServicePort";
private const int remoteUpdateServicePortDefault = 0xc3c;
private const string ruleDisplayStringExtractorClass = "RuleDisplayStringExtractorClass";
private const string ruleDisplayStringExtractorClassDefault = "Microsoft.BizTalk.RuleEngineExtensions.RuleDisplayStringExtractor";
private const string ruleDisplayStringExtractorDll = "RuleDisplayStringExtractorAssembly";
private const string ruleDisplayStringExtractorDllDefault = "Microsoft.BizTalk.RuleEngineExtensions";
private const string schemaLocation = "InstallPath";
private const string schemaLocationDefault = null;
private const string sqlTimeout = "SqlTimeout";
private const int sqlTimeoutDefault = -1;
private const string staticsSupported = "StaticSupport";
private const int staticsSupportedDefault = 0;
private const string trackingInterceptorClass = "TrackingInterceptorClass";
private const string trackingInterceptorClassDefault = "";
private const string trackingInterceptorDll = "TrackingInterceptorAssembly";
private const string trackingInterceptorDllDefault = "";
private const string translationTimeout = "TranslationTimeout";
private const int translationTimeoutDefault = 0xea60;
private const string updateServiceMessageAuthenticationLevel = "UpdateServiceAuthenticationLevel";
private const string updateServiceMessageAuthenticationLevelDefault = "call";
private const string updateServiceMessageClientAssembly = "UpdateServiceClientSinkAssembly";
private const string updateServiceMessageClientAssemblyDefault = "";
private const string updateServiceMessageClientClass = "UpdateServiceClientSinkClass";
private const string updateServiceMessageClientClassDefault = "";
private const string updateServiceMessageImpersonationLevel = "UpdateServiceImpersonationLevel";
private const string updateServiceMessageImpersonationLevelDefault = "impersonate";
private const string updateServiceMessageSecurityPackage = "UpdateServiceSecurityPackage";
private const string updateServiceMessageSecurityPackageDefault = "ntlm";
private const string updateServiceMessageServerAssembly = "UpdateServiceServerSinkAssembly";
private const string updateServiceMessageServerAssemblyDefault = "";
private const string updateServiceMessageServerClass = "UpdateServiceServerSinkClass";
private const string updateServiceMessageServerClassDefault = "";

No comments: