22 Jan 2009

AD Lookup Control in Request Tracker

So my double header post on getting this funky AD lookup control with Perl (post 1 & post 2) was actually prep work for getting to work in a product called RT (or Request Tracker from BestPractical) which is built on Perl. I have never worked with it before so I am slightly (read: exceptionally) ignorant of how to do this. Effectively I want a lookup to include AD users.

The First Option

The first thing I saw was this Include Page option when creating a field, which is described as

RT can include content from another web service when showing this custom field. Fill in this field with a URL. RT will replace __id__ and __CustomField__ with the record id and custom field value, respectively Some browsers may only load content from the same domain as your RT server.

image

Sounds perfect, turns out there is NO knowledge of how this works. I tried various forums and news groups, even emailing people who asked before about it… no answers are available! The documentation is USELESS!

The Second Option

Another option is once you have created a field a new option appears: Field values source:

image

So how do you actually use this without typing in the options yourself?

Custom Perl Module

Well in the /opt/rt3/lib/RT/CustomFieldValues is a file called Groups.pm which allows you to provide the names of the groups as a field source. So this is a possible solution, but first you need to create the module. The module has two methods:

SourceDescription - Which needs to return a string containing the name of what you are returning.

ExternalValues - Which needs to return an array of objects which contain the values. Those object must have a name property which is the name you want to show, and two optional properties description which is the… actually I dunno where it’s used (don’t think it is) and sortorder which you use to do the sorting. So taking the AD code previous the previous posts and combining it into the right format we end up with this code:

package RT::CustomFieldValues::AD;
 
#Start of user configurable settings
 
my $DomainController = "<SERVER>";
my $Username = "<USERNAME@DOMAIN>";
my $Password = "<PASSWORD>";
my $BaseOU = "<SEARCH OU>";
 
#End of user configurable settings
# ------------------- DO NOT CHANGE FROM HERE ---------------
#Start of system settings
my $Attributes = "sAMAccountName,sn,displayName";
my $Filter = "(objectCategory=User)" ;
#End of system settings
 
 
use strict;
use warnings;
use Net::LDAP;
use Net::LDAP::Control::Sort;
use HTML::Entities;
 
use base qw(RT::CustomFieldValues::External);
 
sub SourceDescription {
    return 'Active Directory Users';
}
 
sub ExternalValues {
    
    my @res;
    my $i = 0;
    my $ad = Net::LDAP->new($DomainController)
                or die "Could not connect!";
 
    $ad->bind($Username, password=>$Password, version=>3);
 
    my $sort = Net::LDAP::Control::Sort->new(order => "displayName");
 
    my $results = $ad->search(base=>$BaseOU, filter=>$Filter, attrs=>    $Attributes, control=>[$sort]);
    
    if ($results->count == 0)
    {
      die "No results returned";
    }
    else
    {
        for (my $counter=0; $counter<$results->count; $counter++)
            {
            my $user = $results->entry($counter);
                    if (defined($user->get_value("sn")) && length($user->get_value("sn")) > 0 && defined($user->get_value("sAMAccountName")))
                    {
                push @res, {
                    name => encode_entities($user->get_value("displayName")),
                description => encode_entities($user->get_value("sAMAccountName")),
                sortorder => $i++,
 
                }
            }
            }
      }
 
    $ad->unbind;
 
 
      return \@res;
}
 
1;

So we bundle that nicely in to AD.pm and dump that into the folder.

Configuration

So how do we use that module? Well you need to go to /opt/rt3/etc and edit the RT_SiteConfig.pm file and add the following line to it: Set(@CustomFieldValuesSources, "RT::CustomFieldValues::AD");

Next restart Apache (the command I used was: apache2ctl restart) and go back to the field properties and you should be able to select it.

Tips and Tricks

A few things about building these that I learnt along the way

  1. If, after the IIS reset, there is no drop down for the field source it means you have a bug in a module and you need to fix said bug.
  2. Use the die command excessively. When you select the field source and click save changes it will test your code. Only die will cause it to show error messages! When you get the UI, it will not give you errors!
  3. The autocompletion options may seem the coolest, but they use a (poorly, at least compared to jQuery) written piece of JavaScript. This battles to run with more than 25 results returned (slows down, doesn’t work, errors, freezes browser). I would recommend working with the select one or select many (combo boxes) first and trying to change to it later.
  4. If you change the code after you have set the field, you need to restart apache and then re-configure the field by setting the field source to something else, save and then set it back. It seems there is some caching issues which can prevent your changed results from appearing.

Hopefully this helps you develop with RT, and that this (overcomplicated) process is easier.

16 Jan 2009

AD Lookup Control with Perl and JS - Day 2

So day 2 started with growing the control further, but first I wanted to set the code up to run in IIS.

Perl + IIS 7

First I created a simple application pool for this site to run in. One of the nice things is setting it to not run .NET Framework code, which just lowers your attack surface.

image

Next I created a simple web site to use that app pool, however there was no handler setup (odd, I thought ActivePerl’s install did this - but maybe it is IIS 6 only). To fix that I clicked on Handler Mappings

image

In there I added a Script Handler with the following settings:

image

Note I would leave Request Restrictions on the default UNLESS you have a good reason to do it.

After that brief config my Perl worked for a while, until I started getting this error (IIS Worker Process has stopped working) when browsing to the web page:

image

I had just changed code before that, so here is a quick test to you to try and find the fault. The snippet of Perl code looks like the following:

   1: print "<html> 
   2: <head> 
   3: <script src='jquery.js' type='text/javascript'></script>
   1:  
   2: <script src='jquery.simplemodal.js' type='text/javascript'>
   1: </script> 
   2: <script src='test.js' type='text/javascript'>
</script>
   4:  
   5: </head> 
   6: <body style='font-family: Calibri'> 
   7:  
   8: Username <input type='text' id='result' readonly='readonly'/><span id='test' style='color: #0000FF; text-decoration: underline; cursor: hand'>Select User</span> 
   9:  
  10: <div id='listContent' style='padding: 5px; background-color: #000000; color: #FFFFFF; border: thin solid #C0C0C0; width: 450px; overflow: scroll; height: 450px;'> 
  11: <div style='font-size: x-small; color: #C0C0C0; text-align: right; cursor: hand;padding-right: 20px;' class='simplemodal-close'>Cancel</div> 
  12: <span style='text-transform: capitalize; font-weight: bold; padding-bottom: 3px'>Select a user by clicking on their name</span> 
  13: <hr /> 
  14: Filter <input type="text" id="filter" /> 
  15: <hr />";

If you are stuck the here is a hint: Line 14.

.

.

.

Ok, if you got it good. If not, well it is because the HTML I was outputting had " in it and that caused the string to close and some garbage (from the compilers POV) to be after it. Why this has to kill the process I dunno, what’s wrong with a error message like we get from .NET?!

Filtering

I added a text box to the popup dialog so I could filter using JQuery .show and .hide methods. This is not that impressive but it did lead me to needing the jQuery documentation a lot (mainly for the selectors, but I also was getting weird results with hide… until I realized I had <br/> tags there and those weren’t getting hidden) and checking with the slow internet here was not great. So I found (read: I went to the jQuery Alternative Resources page) a cheat sheet I could print and stick on the wall in front of me. There are two listed there, one Excel and one Image. The image one looks nicer and is more verbose than the Excel one, but I went with the Excel one because it has examples… and I can figure out from the examples more than the verbose text in the image gives me.

One of the other things about filtering is that I wanted to be case insensitive, but I was using :contains to do the filtering which is case sensitive. I found a great thread on adding an extension method to it with a case insensitive version of :contains. I recommend if you are stuck copy/paste that one.

12 Jan 2009

Delphi Prism - Part 1: Opening the "box"

All Prism related posts can be found in the tag Prism.

Hi, my name is Robert. I have been a closet Delphi fan for many years. <Hi Robert>. So when Borland, sorry Interprise, no I was right it’s Borland, sorry I forgot CodeGear, never mind I think it’s no Embarcadero said there was a super duper new version coming I got excited (maybe too much). So I have downloaded the trial and will blog about the experience. Now note Delphi is NOT what I use day to day, in fact if I am choosing a language now it’s C# so don’t expect production evaluations but rather a hackers evaluations. First thing is downloading it (and finding my BDN CDN login) and waiting for the 4Gb to download to the slow internet of South Africa.

So lets see what’s in the box, or image:

image

First is ER/Studio Developer Edition which is a database modeling tool from Embarcadero.

InstallAware Express CodeGear edition is an installer system, ala MSI/InstallShield/NSIS etc…

InterBase 2009 Developer Edition is next, no need to mention what that is (Delphi fans will just know)

Mono is exciting, in there is the Win32 GTK version of Mono :) Cross platform dreams are coming back.

Shell contains the VS 2008 shell install.

Wiki is interesting, as it looks like a dump (dated September 29, 2008) of the one from their site with anything other than read disabled. This makes sense and is actually very useful for us in the slow internet land who may battle to get to the wiki some times. So to who ever had this idea, well done! A few of the articles that jumped out at me are:

  • Win32 Delphi vs. Delphi Prism
  • Delphi Prism Syntax compared with Win32 Delphi
  • Migration Tools: Oxidizer – ShineOn

There is also a good logo:

00b57c86-5c6a-44a3-8d4d-5b1466b70048

12 Jan 2009

AD Lookup Control with Perl and JS - Day 1

Recently I needed to do a bit of coding for a project which needed a lookup system into Active Directory written in Perl, this post explorers the excitement (read: pain) that I had with this bit of coding. I haven't touched Perl since for a few years but development is like riding a bike, isn’t it?

Setup

First problem is I used to “ride” a Linux bike where Perl is part and parcel of the world, now this Windows 2008 Server which I use on my laptop it’s another story. So step one is getting Perl for Windows, and thankfully the parts of my memory not (yet) destroyed by beer remembered about Active Perl from Active State which had a Windows version (this takes me back almost a decade to when I last used Active Perl, go strong brain cells, go!). The download and install of it was very painless, it just did it’s thing.

Next up was getting an IDE in place just to get up and running, so I found Perl Express which is a free, small IDE for Windows. It has a built in debug environment which is all I really needed. When I get to the later stuff I was confusing it with my “small” script. Lots of people have told me to get Slick Edit instead as it is much better, but it costs money and I need this for a short while. If I had to do this daily I would invest in a real one.

Install NET:LDAP Attempt 1

Next up was finding out how Perl can talk to AD. I decided that there must be LDAP support so I would look for that and found a great series on using NET::LDAP (the link goes to Bundle::NET::LDAP, but I’ll explain that later) when working with AD, you can read part 1 of that here. So I fired up Perl Express and tried the first sample and it died saying I do not have NET::LDAP. So off to find out how to get the module, which turns out needs to be obtained via the command line by typing

perl -MCPAN -e "install Net::LDAP"

However since it has dependencies it is better to get the bundle pack with everything in it so you type

perl -MCPAN -e "install Bundle::Net::LDAP"

This will download, compile and install the module. The first time I ran the command it failed because my proxy at work was blocking me, so time for the trusty 3G connection.

Install NET:LDAP Attempt 2

Run the command for a second time and it starts to fail with this pop-up:

image

See it needs to do a compile and when it can’t find NMake it downloads it from Microsoft. However it downloads the old 16bit version and that doesn’t run on 64bit Windows 2008 :( The internet suggested I download the Windows SDK since it had a 32bit and I found it at: Windows SDK for Windows Server 2008 and .NET Framework 3.5 but it is huge (min of a couple hundred Megs of download). But I thought I have Visual Studio installed, surely that has a copy?

Thankfully, my search kung fu (I have to stop calling skills Kung Fu - watching X-Files is doing this to me) is not limited to the in#ternets and I found a local version. To use it I needed to run the following at the command prompt PRIOR to running my perl install:

"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"

Install NET:LDAP Attempt 3

Right, attempt number 3. This failed due to missing dependencies, you’d think when it comes up and asks you

==> Auto-install the 1 optional module(s) from CPAN? [n]

for said dependency it would do that when you say yes? Doesn’t seem so. It seems it is just a test to how many times you will run the tool.

Install NET:LDAP Attempt 4 & 5

*sigh* So now I will try and install each dependency manually first, so the commands look like this:

"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"

perl -MCPAN -e "install GSSAPI"

perl -MCPAN -e "install IO::Socket::SSL"

perl -MCPAN -e "install XML::SAX::Writer"

perl -MCPAN -e "install Bundle::Net::LDAP"

This still complained about issues, so I run each one again (ignoring errors - ignorance is bliss) and when prompted I choose the default of no, and somehow even with errors (I think they are errors, maybe I just not used to reading these message) there in C:\Perl\site\lib\ appeared a NET folder with an LDAP.pm file in it!

5 Attempts and it is installed - yeah just like riding a bike :/

Finding my Domain Controller

The first thing I need to provide to NET::LDAP is my domain controller, which I don’t know so instead of logging a call with IT and waiting for a response I decided to figure it out myself. Thankfully I found a page on Microsoft’s site detailing How Domain Controllers are located in Windows which included directions on troubleshooting problems. One of those was manually testing with the command line

nltest /dsgetdc:<your domain>

which provided exactly what I needed!

Control Construction Step 1 - Getting the details

The first part of  building my lookup control was to be able to query AD for all users and just list it back. I defined a user as someone with a surname greater than zero and with a username, if you had those you are a user and not a machine or system account (yes, SkyNet I’m looking for you).

The script in the end looked like this:

#!/usr/bin/perl
 
use strict;
use Net::LDAP;
use Net::LDAP::Control::Sort;
 
#Start of user configurable settings
my $DomainController = "<DOMAIN CONTROLLER>";
my $Username = "<USERNAME@DOMAINNAME>";
my $Password = "<PASSWORD>";
my $BaseOU = "<BASE OU>";
#End of user configurable settings
#Start of system settings
my $Attributes = "sAMAccountName,sn,displayName";
my $Filter = "(objectCategory=User)" ;
#End of system settings
 
print "Going to attempted to connect to ".$DomainController;
 
my $ad = Net::LDAP->new($DomainController)
                or die "Could not connect!";
 
$ad->bind($Username, password=>$Password);
 
my $sort = Net::LDAP::Control::Sort->new(order => "displayName");
 
 
my $results = $ad->search(base=>$BaseOU, filter=>$Filter, attrs=>$Attributes, control=>[$sort]);
if ($results->count == 0)
{
  die "No results returned";
}
else
{
    for (my $counter=0; $counter<$results->count; $counter++)
        {
            my $user = $results->entry($counter);
                if (defined($user->get_value("sn")) && length($user->get_value("sn")) > 0 && defined($user->get_value("sAMAccountName")))
                {
                    print "\nUser Found:".$user->get_value("displayName")." (".$user->get_value("sAMAccountName").")";
                }
        }
}
 
$ad->unbind;
 
print "\nDone";

Since I don’t deserve to be called a Perl programmer (I have no skills here), this Perl Hacker did rely on the internet for help. The sites that helped me were:

Control Construction Step 2 - The HTML

Since this will be a web page what I would like to do is have a page popup when you click on a text box which will let you select a user. When ever I have these scenarios I like to simply the development by creating an HTML file or two on my desktop and getting the JavaScript to work on a very tightly built scenario. This way I get the thinking and structure right without worrying about bugs being caused because of data or the perl code. Since I am going to use JavaScript it means I need to grab a copy of everyone’s (maybe not everyone, but at least me, the guys at End User SharePoint and Microsoft) favorite JS library, jQuery. That is followed by a wander through the plug-in section on jQuery to see if anyone has done what I need already (hey, I’m a busy man and don’t have time to reinvent every wheel), besides the WOW factor of some of those demo’s is just so high I get all geeked out by it. Thankfully I found Eric Martin’s wonderful Simple Modal plug-in which allowed me to put together a nice mashup of the HTML and “pop-ups”.

 

You can grab the source code for that mashup by clicking download below (you’ll need 7-zip to open it).

06 Jan 2009

Tripping over logs: A story of Unity - Part 6

Intro

The final post in the series :) Get the code here, read comments on unit testing with DI, thanks, references and further reading!

This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:

This is just a final post to wrap up the series, you really should use the above links to get the actual value out of it.

Download the Final Code

You will need 7-Zip to open it.

My view on Unit Testing with DI

What excited me about DI initially is that it makes testing and in particular unit testing, so much better. The problem faced with any system you want to test is that if it is tightly coupled you can’t unit test, you can only do integration testing. By following DI, you are forced into a loosely coupled architecture which means that you can very easily test your individual components.

Let me give you a real world story on this, which involved the enterprise system I mentioned in the very first post. It read from system A, did processing and wrote to system B. The fact it was tightly coupled meant that I couldn’t even fake a message into the system, I had to generate real messages in system A and watch the flow of those messages. After a long time I dropped MSMQ between system A, the processing and system B to enable me to fake messages but even then it wasn’t great as I needed to re-write so much code to talk to these new interfaces. Lastly the processing took many hours to run to completion so proper end to end testing took days, and if a crash occurred certain processes needed to be started from scratch again.

If I had used DI for the system the first thing I could’ve done is written up two mock interfaces and swopped with real ones out using the config. This would mean I could simulate messages simply. System B was in fact MSCRM which I couldn’t run on my machine (laptop running Windows XP at the time) so being able to mock the interface to it could’ve meant that I could’ve worked on the processing engine without MSCRM being needed (i.e. a VM or server).

Next the tightly coupling of methods meant that the process had to run it’s time, but if I had implemented DI I would have each of the individual components of the processing separated out and would be able to have tested them individually. Yes, end to end processing would still be needed but I could’ve saved days of testing with this.

I haven’t actually done enough to write a post on this specific topic, so maybe once I have done more I will be more sure or maybe I will just tell you I was wrong.

Thanks, References and Further Reading

First off thanks to you, the reader, for spending time on this series and I hope you drop me a mail/@rmaclean/comment if this has helped you or you have any questions.

That said I could not have done with without a great posts I found on this subject - so here is my references:

Note that Unity is an implementation of this, there is a lot of them out there. Scott Hanselman has a list at  http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx

Lastly I could not end this series without a link to the definitive theory on DI, by Martin “wolfman” Fowler - Inversion of Control Containers and the Dependency Injection pattern. This is a must read for everyone.

The other must read is Jacob Proffitt (http://theruntime.com/blogs/jacob/Default.aspx) who is a .NET expert/guru etc… but is not a fan of DI. The reality check you will get from him should help balance the DI fan-boy crowds out.

06 Jan 2009

Tripping over logs: A story of Unity - Part 5

Recap + Intro

In part 1 we looked at the problem with just adding logging code and how it quickly gets messy and we looked at how the more loosely coupled the code is, the easier it is to effect changes painlessly. Then in part 2 we took that code and added Unity which gave us control via a config file as to what class our logging should use. Then in part 3 we saw some benefits of dealing with this overhead. Previously we actually got our logging nicely sorted but there was a few extra details worth mentioning, so here goes.

Note you can get Unity with the Enterprise Library from p&p group.

As I said in part 1

what I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job. If you want the theory look somewhere else, if you want to get running with Unity this is for you.

This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:

Circular References

DI is actually a minefield since you can cause a circular reference easily, but injection makes that even easier to shoot yourself in the foot. What is a circular reference? The documentation (shockingly) describes it well:

  • Objects generated through constructor injection that reference each other in their constructor parameters
  • Objects generated through constructor injection where an instance of a class is passed as a parameter to its own constructor
  • Objects generated through method call injection that reference each other
  • Objects generated through property (setter) injection that reference each other

For example, the following code shows two classes that reference each other in their constructors.

public class Class1
{
  public Class1(Class2 test2)
  { ... }
}
 
public class Class2
{
  public Class2(Class1 test1)
  { ... }
}

It is the responsibility of the developer to prevent this type of error by ensuring that the members of classes they use with dependency injection do not contain circular references.

I have bolded that last line to get the point across. You have been warned!

Reflection

It’s not just interception that uses reflection, other parts do as well so make sure you understand the security implications of this: http://msdn.microsoft.com/en-us/library/9syytdak.aspx

Interceptors

I used the transparent proxy interceptor in my previous post, but there are two others. Each has pro’s and con’s, which the documentation puts in a simple table for you:

Type

Description

Use

TransparentProxyInterceptor

An instance interceptor. The proxy is created by using the .NET TransparentProxy/RealProxy infrastructure.

When the type to intercept is a MarshalByRefObject or when only methods from the type's implemented interfaces need to be intercepted.

InterfaceInterceptor

An instance interceptor. It can proxy only one interface on the object. It uses dynamic code generation to create the proxy class.

When resolving an interface mapped to a type.

VirtualMethodInterceptor

A type interceptor. It uses dynamic code generation to create a derived class that gets instantiated instead of the original, intercepted class and to hook up the call handlers.

When only virtual methods need to be intercepted.

Selection of a specific interceptor depends on your specific needs, because each one has various tradeoffs. The following table summarizes the three interceptors and their advantages and disadvantages.

Type

Advantages

Disadvantages

TransparentProxyInterceptor

Can intercept all methods of the target object (virtual, non-virtual, or interface).

The object must either implement an interface or inherit from System.MarshalByRefObject. If the marshal by reference object is not a base class, you can only proxy interface methods. The TransparentProxy process is much slower than a regular method call.

InterfaceInterceptor

Proxy supports casting to all the interfaces or types of the target object.

It only intercepts methods on a single interface. It cannot cast a proxy back to target object's class or to other interfaces on the target object.

VirtualMethodInterceptor

Calls are much faster than the TransparentProxyInterceptor.

Interception only happens on virtual methods. You must set up interception at object creation time and cannot intercept an existing object.

Rules

There is an entire rules framework available in interception which lets you enable/disable the interception based on rules. The idea is that you annotate all methods and then use the rules to filter which of those to actually run. This can, as with everything in Unity, be configured in code or in the configuration file. Here are a list of the rules (I am sure you can begin to guess what they do by their names):

  • The Assembly Matching Rule
  • The Custom Attribute Matching Rule
  • The Member Name Matching Rule
  • The Method Signature Matching Rule
  • The Namespace Matching Rule
  • The Parameter Type Matching Rule
  • The Property Matching Rule
  • The Return Type Matching Rule
  • The Tag Attribute Matching Rule
  • The Type Matching Rule

And as always you can custom develop your own rules too.

06 Jan 2009

Tripping over logs: A story of Unity - Part 4

Recap + Intro

In part 1 we looked at the problem with just adding logging code and how it quickly gets messy and we looked at how the more loosely coupled the code is, the easier it is to effect changes painlessly. Then in part 2 we took that code and added Unity which gave us control via a config file as to what class our logging should use. Then in part 3 we saw some benefits of dealing with this overhead, but now dear reader we get into the real issue I wanted to solve, having logging be more elegantly applied.

Note you can get Unity with the Enterprise Library from p&p group.

As I said in part 1

what I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job. If you want the theory look somewhere else, if you want to get running with Unity this is for you.

This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:

Works better than Vader’s interceptor

(Once again I shine my knowledge of Star Wars in a title… which maybe is why my friends and family think of me as a geek and I see myself as cool… anyway it’s not important to the post.)

The Mary Poppins bag like magic that is happening with Unity is NOT just limited to controlling the lifetime of objects, it is actually controlling the objects. There is an invisible layer there and this allows us to do something very smart called Interception. In this scenario we intercept calls to classes or methods and apply some other code to them! Important to note is that we can only do that to objects that Unity works with so for our example, we can’t do it to the main method or the DoSomething method directly. We can refactor DoSomething into it’s own interface and class and have Unity own it as below. The key changes from our previous code are:

  • I create a instance of IWorker and do the DoSomething method of it, passing it the logger - lines 14 and 15
  • I have a new interface called IWorker and a new class based on it, called Worker - Lines 43 to 55
  • I have removed our Lolzcat’s constructor in the logging (it’s not important to show that anymore)

   1: class Program
   2:     {
   3:         static IUnityContainer container = new UnityContainer();
   4:  
   5:         static void Main(string[] args)
   6:         {
   7:             UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
   8:             section.Containers.Default.Configure(container);
   9:  
  10:             ILogger logger = container.Resolve<ILogger>();
  11:  
  12:             logger.LogThis("Application started");
  13:  
  14:             IWorker worker = container.Resolve<IWorker>();
  15:             worker.DoSomething("Robert", logger);
  16:  
  17:             Console.ReadKey();
  18:             logger.LogThis("Application Completed");
  19:         }
  20:     }
  21:  
  22:     public interface ILogger
  23:     {
  24:         void LogThis(string Message);
  25:     }
  26:  
  27:     public class DebugLogger : ILogger
  28:     {
  29:         public void LogThis(string Message)
  30:         {
  31:             System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
  32:         }
  33:     }
  34:  
  35:     public class ConsoleLogger : ILogger
  36:     {
  37:         public void LogThis(string Message)
  38:         {
  39:             Console.WriteLine("{0}: {1}", DateTime.Now, Message);
  40:         }
  41:     }
  42:  
  43:     interface IWorker
  44:     {
  45:         void DoSomething(string Username, ILogger logger);
  46:     }
  47:  
  48:     public class Worker : IWorker
  49:     {
  50:         void IWorker.DoSomething(string Username, ILogger logger)
  51:         {
  52:             logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
  53:             Console.WriteLine("Hello {0}", Username);
  54:             logger.LogThis("DoSomething Completed");
  55:         }
  56:     }

So this runs nicely but we are still using this logger thing all the time and it isn’t much better than before.

Setup the Interception

So to fix this we will use interception and that means we need to add two more references to our solution:

image

Next we add a new using to our code:

using Microsoft.Practices.Unity.InterceptionExtension;
using System.Reflection;

Yes, that is System.Reflection there. We will use reflection to figure out values at runtime for us.

And now we will add in code to allow us to attribute our methods so that logging happens for us. For those who have no idea what I mean by attribute methods, I am talking about the Decorator Pattern, which will be familiar to those using WCF and/or LINQ at least in practice even if you didn’t know it was called that.

To do that we first need to create another new class, this time derived from HandlerAttribute and all it does is gives us the attribute to decorate the code with, lines 1 to 7 below. It returns a class of LoggingHandler (via the container) and LoggingHandler is the other new. In here we have a constructor which take an instance of ILogger (lines 13 to 16) and a Invoke method (starting on line 18). The invoke method is the brains of the operation as it is what will be run when we call our method. Note it starts with us using reflection to work out the parameters (lines 20 through 25) and then calls the logger to write the PRE method message (line 27). Next it calls getNext which gets the next handler in the stack (in our case there is none). Note you control the order of handlers via the Order parameter, line 34. After all the handlers have run their PRE methods the method actually runs, and after the getNext it starts to unwind so we can do our POST method logging, line 29.

   1: public class LoggingAttribute : HandlerAttribute
   2:     {
   3:         public override ICallHandler CreateHandler(IUnityContainer container)
   4:         {
   5:             return container.Resolve<LoggingHandler>();
   6:         }
   7:     }
   8:  
   9:     public class LoggingHandler : ICallHandler
  10:     {
  11:         ILogger _logger;
  12:  
  13:         public LoggingHandler(ILogger logger)
  14:         {
  15:             _logger = logger;
  16:         }
  17:  
  18:         public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
  19:         {
  20:             string parameters = string.Empty;
  21:             for (int counter = 0; counter < input.Inputs.Count; counter++)
  22:             {
  23:                 ParameterInfo parameterInfo = input.Inputs.GetParameterInfo(counter);
  24:                 parameters += parameterInfo.Name + " = " + input.Inputs[counter].ToString() + Environment.NewLine;
  25:             }
  26:  
  27:             _logger.LogThis(String.Format("About to call {0} with the following parameters: {1}", input.MethodBase.Name, parameters));
  28:             IMethodReturn msg = getNext()(input, getNext);
  29:             _logger.LogThis(String.Format("Call completed to {0}", input.MethodBase.Name));
  30:  
  31:             return msg;
  32:         }
  33:  
  34:         public int Order { get; set; }
  35:     }

One point I want to make here, and I think it is super cool, is note I never specify what to pass into LoggingHandler’s constructor (it needs an ILogger parameter)! Unity is smart enough to know it has an ILogger in the container and a constructor with needs one and puts them together automatically for you ;)

Right that’s a lot of code to do this, so how does it effect our other code? We’ll now our DoSomething method just looks like this below. Note the [Logging] attribute tag on line 1 which enables the logging for this method.

   1: [Logging]
   2: void IWorker.DoSomething(string Username)
   3: {
   4:     Console.WriteLine("Hello {0}", Username);
   5: }

If you think that in a massive system the fact we can just annotate methods to get functionality is great, it cleans the code up and means that developer X who is working on logging can change it WITHOUT any code changes :) Rock On!

Configuration for Interception

Our code does not run at this point :( Because we need to add some details the app.config for the system to use configuration. First we add an alias for our chosen method of interception on line 14, then we extend the unity config (similar concept to how we extended the .NET config with a config section) on lines 28 to 30, and lastly we configure the extension we added. The most important part here is how we link an interceptor to a class (lines 35 and 36). This means we can enable/disable interception via configuration.

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:     <configSections>
   4:         <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
   5:     </configSections>
   6:  
   7:     <unity>
   8:         <typeAliases>
   9:             <typeAlias alias="Logger" type="BigSystem.ConsoleLogger, BigSystem"/>
  10:             <typeAlias alias="ILogger" type="BigSystem.ILogger, BigSystem"/>
  11:             <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
  12:             <typeAlias alias="Worker" type="BigSystem.Worker, BigSystem"/>
  13:             <typeAlias alias="IWorker" type="BigSystem.IWorker, BigSystem"/>
  14:             <typeAlias alias="transparentProxy" type="Microsoft.Practices.Unity.InterceptionExtension.TransparentProxyInterceptor, Microsoft.Practices.Unity.Interception" />
  15:         </typeAliases>
  16:  
  17:         <containers>
  18:             <container>
  19:                 <types>
  20:                     <type type="ILogger" mapTo="Logger">
  21:                         <lifetime type="singleton" />
  22:                     </type>
  23:                     <type type="IWorker" mapTo="Worker">
  24:                         <lifetime type="singleton" />
  25:                     </type>
  26:                 </types>
  27:  
  28:                 <extensions>
  29:                     <add type="Microsoft.Practices.Unity.InterceptionExtension.Interception, Microsoft.Practices.Unity.Interception" />
  30:                 </extensions>
  31:  
  32:                 <extensionConfig>
  33:                     <add  name="interception" type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationElement, Microsoft.Practices.Unity.Interception.Configuration">
  34:                         <interceptors>
  35:                             <interceptor type="transparentProxy">
  36:                                 <default type="IWorker"/>
  37:                             </interceptor>
  38:                         </interceptors>
  39:                     </add>
  40:                 </extensionConfig>
  41:             </container>
  42:         </containers>
  43:     </unity>
  44: </configuration>

And that is it! It’s been a long post so I won’t go into any specific of the interception type etc… I’ll do a supplementary post on that next.

06 Jan 2009

Tripping over logs: A story of Unity - Part 3

Recap + Intro

In part 1 we looked at the problem with just adding logging code and how it quickly gets messy and we looked at how the more loosely coupled the code is, the easier it is to effect changes painlessly. Then in part 2 we took that code and added Unity which gave us control via a config file as to what class our logging should use. Now we are going to look at a benefit of having this Mary Poppins bag of magic controlled for us.

Note you can get Unity with the Enterprise Library from p&p group.

As I said in part 1

what I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job. If you want the theory look somewhere else, if you want to get running with Unity this is for you.

This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:

The time of your life

In our code we created a global variable for the logging and just called that, but that is not always a good idea. Logging is a poor example of this, but security is a better one. If you wanted to do a security check in some methods and not others why waste time with a global variable, why not reach into the bag each time it is needed and pull one out. The problem can come in, is that performance can drop because now you are calling the constructor each time you need the object. The reality is that this issue was solved years ago in the Singleton pattern.

So can we apply that to Unity? Yes, Unity is smart enough to give us a way to do that thanks to it’s inbuilt lifetime management! To demo this I have modified the code from part 2 as follows:

  • Removed the global variable for logger and replaced it with a global variable for the container (line 3 below)
  • In DoSomething I ask for a logger at the start now (line 7 below)
  • I got a Lolzcat to add a constructor to my ConsoleLogger class to slow it down ;) Lines 45 to 49.
  • It’s not visible in the code by a new using has been added to System.Threading so that we can use the Thread.Sleep method on line 48
   1: class Program
   2:     {
   3:         static IUnityContainer container = new UnityContainer();
   4:  
   5:         static void DoSomething(string Username)
   6:         {
   7:             ILogger logger = container.Resolve<ILogger>();
   8:  
   9:             logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
  10:             Console.WriteLine("Hello {0}", Username);
  11:             logger.LogThis("DoSomething Completed");
  12:         }
  13:  
  14:         static void Main(string[] args)
  15:         {
  16:             UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
  17:             section.Containers.Default.Configure(container);
  18:  
  19:             ILogger logger = container.Resolve<ILogger>();
  20:  
  21:             logger.LogThis("Application started");
  22:  
  23:  
  24:             DoSomething("Robert");
  25:             Console.ReadKey();
  26:             logger.LogThis("Application Completed");
  27:         }
  28:     }
  29:  
  30:     public interface ILogger
  31:     {
  32:         void LogThis(string Message);
  33:     }
  34:  
  35:     public class DebugLogger : ILogger
  36:     {
  37:         public void LogThis(string Message)
  38:         {
  39:             System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
  40:         }
  41:     }
  42:  
  43:     public class ConsoleLogger : ILogger
  44:     {
  45:         public ConsoleLogger()
  46:         {
  47:             Console.WriteLine("i iz in yourz codez, slowingz its downz");
  48:             Thread.Sleep(5000);
  49:         }
  50:  
  51:         public void LogThis(string Message)
  52:         {
  53:             Console.WriteLine("{0}: {1}", DateTime.Now, Message);
  54:         }
  55:     }

What happens if my code runs slowly now and the lolzcat message is shown twice (since I create the object twice). If I assume that it’s just an example of the overhead of the constructor (which it is), and that I need to live with it at least once then implementing the singleton pattern is the solution to this. To do it actually means two lines of changes to the app.config (one line if you want to be messy). First I add a new type alias for the ContainerControlledLifetimeManager which I have called singleton (line 11 below), and then I expand my type with a lifetime tag which links back to it (line 18 below).

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:     <configSections>
   4:         <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
   5:     </configSections>
   6:  
   7:     <unity>
   8:         <typeAliases>
   9:             <typeAlias alias="Logger" type="BigSystem.ConsoleLogger, BigSystem"/>
  10:             <typeAlias alias="ILogger" type="BigSystem.ILogger, BigSystem"/>
  11:             <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
  12:         </typeAliases>
  13:  
  14:         <containers>
  15:             <container>
  16:                 <types>
  17:                     <type type="ILogger" mapTo="Logger">
  18:                         <lifetime type="singleton" />
  19:                     </type>
  20:                 </types>
  21:             </container>
  22:         </containers>
  23:     </unity>
  24: </configuration>

Now I just rerun my application and I get the code twice as fast and one lolzcat message since the container (magic bag) has now created the object once and when I ask for it a second time it provides me the already created one! This is an amazingly useful system because it’s per mapping and out of the box are three lifetime managers and you can build your own.

For the sake of ease I will now copy and paste from the documentation on those three lifetime managers:

ContainerControlledLifetimeManager. Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects. Unity uses this lifetime manager by default for the RegisterInstance method if you do not specify a different lifetime manager. If you want singleton behavior for an object that Unity creates when you use the RegisterType method, you must explicitly specify this lifetime manager. The behavior is as follows:

  • If you used the RegisterType method to register a type, Unity creates a new instance of the registered type during the first call to the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. Subsequent requests return the same instance.
  • If you used the RegisterInstance method to register an existing object, Unity returns this instance every time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes.

ExternallyControlledLifetimeManager. This lifetime manager allows you to register type mappings and existing objects with the container so that it maintains only a weak reference to the objects it creates when you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes based on attributes or constructor parameters within that class. Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. However, the container does not hold onto a strong reference to the object after it creates it, which means that the garbage collector can dispose of the object if no other code is holding a strong reference to it.

PerThreadLifetimeManager. Unity returns, on a per-thread basis, the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects on a per-thread basis. PerThreadLifetimeManager returns different objects from the container for each thread. The behavior is as follows:

  • If you used the RegisterType method to register a type, Unity creates a new instance of the registered type the first time the type is resolved in a specified thread, either to answer a call to the Resolve or ResolveAll methods for the registered type or to fulfill a dependency while resolving a different type. Subsequent resolutions on the same thread return the same instance.
  • Using the RegisterInstance method to register an existing object results in the same behavior as if you just registered the lifetime container with RegisterType. Therefore, it is recommended that you do not use the RegisterInstance method to register an existing object when using the PerThreadLifetimeManager.
  • PerThreadLifetimeManager returns the object desired or permits the container to create a new instance if no such object is currently stored for the current thread. A new instance is also created if called on a different thread than the one that set the value. This lifetime manager does not dispose the instances it holds.

Pages