Tuesday 10 August 2010

Beware Structure Map - use lazy loading!!!

Our team recently discovered a problem when a site we were responsible for crashed whenever a particular third party web service died. We were wrapping the web service call and catching any errors as is good practice but after 2 crashes in 6 weeks it was necessary to investigate further and we eventually traced the problem back to the Structure Map registry.

We figured the registry was set up to initialise an instance of our
service wrapper on startup so if the third party site was down and our site restarted (via IIS presumably) it couldn’t create an instance of the service wrapper and the whole site would fall over.

var serviceWrapperConfiguration = new ServiceWrapperConfiguration(
new Uri(AppSettings.ServiceUri));

ForRequestedType<IServiceWrapperConfiguration>()
.TheDefault.IsThis(serviceWrapperConfiguration);

ForRequestedType<IServiceWrapper>().TheDefault.Is.ConstructedBy(context =>
{
var configuration = context.GetInstance<IServiceWrapperConfiguration>();
return ServiceWrapperFactory.Create(configuration);
});


Although this was highlighted due to an external dependency
it’s good practice for all Structure Map registries to use lazy loading so once we uncovered the mistake we rewrote the registry to only create an instance when required:

ForRequestedType<IServiceWrapperConfiguration>()
.TheDefault.Is.ConstructedBy(() =>
new ServiceWrapperConfiguration(
new Uri(AppSettings.ServiceUri)));

ForRequestedType<IServiceWrapper>().TheDefault.Is.ConstructedBy(context =>
{
var configuration = context.GetInstance<IServiceWrapperConfiguration>();
return ServiceWrapperFactory.Create(configuration);
});


This was tested throughly by pulling out the network cable on a PC so we lost connection to the third party service and loading the site locally. We were able to step into the website straight away so we're quietly confident this is no longer a problem - worth remembering when setting up Structure Map registries though.