Martijn's blog - E-Commerce, EAI, BizTalk and .NET

2005/10/27

Schema instance generator for use within Orchestrations

Ever ran into a situation where you want to initialize an instance of a used schema? Normally, lots of people use a C# method which loads a string into a XmlDocument instance and return that instance to the Orchestration engine. This is all fine and dandy, but what happens if the schema the original instance string was based on is changed?

I've created a little helper class which instantiates an example fragment of a dynamically selected schema (the Schema needs to be deployed ofcourse). It essentially performs the same task as the "Generate Instance" does within Visual Studio, but without the nodes being repeating a number of times and without serializing the instance to disk. It returns a simple XmlDocument instance containing an instance of the specified schema.

Using this class would enable better maintainability of your Orchestrations, as you need not change any code in the Orchestration itself if you refactor your schemas. Ofcourse, if you're adding or removing fields which are used in the Orchestration, you need to update those as you would normally.

It's located here. Comments are very welcomed! Find my e-mail address here

2005/10/17

BizTalk Server Pipeline Component Wizard - 2006 edition (2.0)

Being sick over the weekend allowed me some time to port the current Pipeline Component Wizard to BizTalk Server 2006.

It has been revised on some portions, improved on others due to VS.NET 2005's enhanced support for CodeDOM (although we're not quite there yet, as per this blog entry).

The wizard now implements regions and has some other neat tricks regarding VS.NET 2005. Check it out once VS.NET 2005 has been released (the current version does not work on beta builds).

Obviously, there's no longer support in this release for BizTalk Server 2004 / VS.NET 2003, as the code has been ported to .NET 2.0.

Get it here.

Let me know what you think (for those with the ability to use the product right now ;-))

2005/10/11

Unit testing BRE policies

When Unit testing BRE policies, it might be useful to be able to declaratively define which RuleStore to use, which Policy to test and which Version to load. Using the Attributes I created, doing this become pretty simple. One of the Attributes also provides for a class Type to be instantiated implementing IRuleSetTrackingInterceptor, which allows tracking what the BRE does while executing the requested Policy. Have a look at the code, as I think it might be useful for many UnitTesting scenarios with version policies.

using it is quite simple:


using MartijnHoogendoorn.BizTalk.BRE.Testing.Attributes;

[Test]
[PolicyTester("MyPolicy", typeof(MyInterceptor))]
[RuleStore("Integrated Security=SSPI;Database=BizTalkRuleEngineDb;Server=MyRuleEngineServer", "MYDOMAIN", "myusername", "mypassword")]

private void TestMyPolicy()
{
  XmlReader reader = new XmlTextReader(@"..\..\..\MyMessage.xml");
  XmlSerializer serializer = new XmlSerializer(typeof(MyMessage));
  MyMessageClass = (MyMessageClass) serializer.Deserialize(reader);

  MyInterceptor interceptor = (MyInterceptor) PolicyTesterHelper.ExecutePolicy(new object[] { "Some interesting value", someObject });
  foreach(string eventLine in interceptor.PolicyExecutionEvents)
  {
    System.Diagnostics.Trace.WriteLine(interceptor.PolicyExecutionEvents.ToString());
  }
}

See the sample code here for a real implementation

2005/10/05

Testing remote Business Rules (BRE)

When using remote Business Rules, you might encounter a situation where you might want to test a policy, stored in a remote SQL Server. I had some security issues, just a tip, here's how I resolved it:

using Microsoft.RuleEngine;

// 0 = LOGON32_PROVIDER_DEFAULT
// 2 = LOGON32_LOGON_INTERACTIVE
IntPtr token = IntPtr.Zero;
   
const string domain = "MYDOMAIN";
const string password = "MYPASSWORD";
const string username = "MYUSERNAME";
const string server = "MYSERVER";

if(LogonUser(username, domain, password, 2, 0, out token) != 0)
{
 WindowsIdentity identity = new WindowsIdentity(token);
 WindowsImpersonationContext context = identity.Impersonate();

 try
 {
  SqlRuleStore ruleStore = new SqlRuleStore(
   string.Format("Integrated Security=SSPI;Database=BizTalkRuleEngineDb;Server={0}", Server));

  RuleSetInfo currentRuleSetInfo = null;

  // retrieve information about the latest published RuleSet from the RuleStore
  RuleSetInfoCollection ruleSets = RuleStore.GetRuleSets(Policy, RuleStore.Filter.LatestPublished);
     
  if(ruleSets.Count > 0)
  {
   // select the retrieved RuleSetInfo object
   currentRuleSetInfo = ruleSets[0];

   // retrieve the latest published RuleSet from the RuleStore
   RuleSet currentRuleSet = RuleStore.GetRuleSet(currentRuleSetInfo);
    
   // create a PolicyTester to test the RuleSet
   PolicyTester tester = new PolicyTester(currentRuleSet);

   tester.Execute(facts, this);
  }
 }
 catch(Exception e)
 {
  System.Diagnostics.WriteLine(e.ToString());
 }
 finally
 {
  context.Undo();
  CloseHandle(token);
 }
}

Ofcourse, as I typed this at heart, some things (like the actual facts being put into the execute action of the PolicyTester) might not compile / work when plainly copied into Visual Studio. Make sure to reference Microsoft.RuleEngine.dll from your project. Also note that this is an example and could be enhanced greatly. ;-)