logo
  • Jobs
  • About Me
  • Contact
  • Home

Archive for April, 2007

Virginia Tech

This is awful.

Police say they’ve preliminarily identified a gunman who massacred 32 people Monday at Virginia Tech in the deadliest shooting rampage in modern U.S. history, cutting down his victims in two attacks two hours apart before the university could grasp what was happening and get the warning out to students.

Words can not even begin to express the sadness that I feel right now. The prayers of a nation are with the students and family who fell victim to the diabolical rage of this shooter.

Absolutely horrifying.

No Comments

Four years and counting

I noticed earlier today that I missed the fourth birthday of this blog. March 31, 2003 saw the first post to this blog. Four years later, I’m still surprised by the success of this site. I want to thank all of my readers for making this possible.

This can not continue without the support of you, dear reader. I encourage you to provide feedback via the comments area on this blog, or via the contact link at the top of every page on the site. Please let me know what you would like to hear me talk more about.

As long as you keep reading, I promise to keep writing. Here’s to four more years…

No Comments

Binding Castle ActiveRecord relationships using select lists

Consider the following data class:

[ActiveRecord("states")]
public class State : ActiveRecordBase<State>
{
	private string name = String.Empty;
	private string abbreviation = String.Empty;
 
	[PrimaryKey(PrimaryKeyType.Assigned, "name")]
	public string Name
	{
		get { return name; }
		set { name = value; }
	}
 
	[Property]
	public string Abbreviation
	{
		get { return abbreviation; }
		set { abbreviation = value; }
	}
 
	public static State[] FindAllOrderedAlphabetically()
	{
		return FindAll(new Order[] {Order.Asc("Name")});
	}
 
	public override bool Equals(object obj)
	{
		if (this == obj) return true;
		State state = obj as State;
		if (state == null) return false;
		return Equals(name, state.name) && Equals(abbreviation, state.abbreviation);
	}
 
	public override int GetHashCode()
	{
		return (name != null ? name.GetHashCode() : 0) + 29*(abbreviation != null ? abbreviation.GetHashCode() : 0);
	}
 
	public override string ToString()
	{
		return name;
	}
}

This is a pretty straightforward ActiveRecord class. The problem comes when you set up a relationship and try to bind this to a select list. A multi-select list comes back as an array of Strings. This clearly can not be bound to a list of State objects. How do you get around this?

As usual, the guys at Castle have already thought about situations like this, and have introduced support for System.ComponentModel.TypeConverter implementations for DataBinding.

public class StateTypeConverter : TypeConverter
{
	public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
	{
		return sourceType == typeof (String);
	}
 
	public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
	{
		return State.Find(value);
	}
}

With this, you can now set use this in your NVelocity view:

$Form.Select("mydata.states", $states, "%{multiple='multiple', size='10}")

and when you bind the mydata prefix in your controller, the states property will use the StateTypeConverter to appropriately convert from string to State.

2 Comments

The beauty of the Chain of Responsibility pattern

As mentioned in a previous post, I’ve been starting to do more and more work with Castle Project’s MonoRail. Most recently, I did some maintenance on a project that I did with a much earlier version of MonoRail.

This project had a base controller that looked something like this:

[Layout("HtmlPage")]
[Rescue("Error")]
public class AbstractPageController : SmartDispatcherController
{
    protected override bool PerformRescue(MethodInfo method, Exception ex)
    {
        ILog log = LogManager.GetLog(this.GetType());
	log.Error(ex);
        return base.PerformRescue(method, ex);
    }
}

Some people may look at this and wonder why exception handling is part of the Controller implementation, clearly violating the Single Responsibility Principle. Hammett and the other folks working on Castle must have thought the same thing. When I upgraded to the latest trunk version of MonoRail, I saw that this code failed to compile.

I looked at the support site for MonoRail and found that they had instead implemented an exception handling extension for MonoRail which would do exactly what I was previously doing in the controller.

Hooking this up was very simple and provided for a much more elegant exception handling. Check this out:

In the web.config, I registed an extension and provided the configuration for the ExceptionChainingExtension:

<monoRail>
    <!-- other config omitted for brevity -->
    <extensions>
      <extension type="Castle.MonoRail.Framework.Extensions.ExceptionChaining.ExceptionChainingExtension, Castle.MonoRail.Framework" />
    </extensions>
 
    <exception>
      <exceptionHandler type="LoggingExceptionHandler, MyAssembly" />
    </exception>
 
    <!-- since I'm planning on logging exceptions, I'll register a log implementation -->
    <services>
      <service id="Custom" type="Castle.Services.Logging.Log4netIntegration.Log4netFactory, Castle.Services.Logging.Log4netIntegration" interface="Castle.Core.Logging.ILoggerFactory, Castle.Core" />
    </services>
</monoRail>

Then, I created the LoggingExceptionHandler class, which looks like this:

public class LoggingExceptionHandler : AbstractExceptionHandler
{
	public override void Process(IRailsEngineContext context)
	{
		ILoggerFactory factory = (ILoggerFactory)context.GetService(typeof (ILoggerFactory));
		ILogger logger = factory.Create(context.CurrentController.GetType());
 
		logger.Error(BuildStandardMessage(context));
		InvokeNext(context);
	}
}

This is fairly straightforward. The only thing that you might wonder about is the InvokeNext call. If you wire up more exceptions in the configuration file (exceptionHandler nodes under the exception element), then this call delegates to the next handler in line.

Let me illustrate this point a little better…

Part of the update of the application involved adding SecurityPermissions to some of the methods on the controllers, and what happens is that every time a method is activated without appropriate permissions, a SecurityException is thrown. This is turn was handled by the LoggingExceptionHandler, which would then log it out to the logger. This was clearly not desired behaviour.

I could have solved this two ways… first, I could have added an if statement in the LoggingExceptionHandler and stop execution if it was a SecurityException. This is a violation of the single responsibility principle. The LoggingExceptionHandler should log an exception, period. Nothing else.

So, the other way to handle this is with an ExceptionFilter… which is just another item in the ExceptionChainingExtension.

In my web.config, I modified the exception node to look like this:

<exception>
  <exceptionHandler type="ExceptionFilter, MyAssembly">
    <exclude type="System.Security.SecurityException, mscorlib" />
  </exceptionHandler>
  <exceptionHandler type="LoggingExceptionHandler, MyAssembly" />
</exception>

and implemented an ExceptionFilter class, which looks like this:

public class ExceptionFilter : AbstractExceptionHandler, IConfigurableHandler
{
	private List<Type> excludedTypes = new List<Type>();
 
	public void Configure(XmlNode exceptionHandlerNode)
	{
		XmlNodeList excludeNodes = exceptionHandlerNode.SelectNodes("exclude");
		foreach (XmlNode excludeNode in excludeNodes)
		{
			string excludedType = excludeNode.Attributes["type"].Value;
			excludedTypes.Add(Type.GetType(excludedType));
		}
	}
 
	public override void Process(IRailsEngineContext context)
	{
		Exception ex = context.LastException is TargetInvocationException
						? context.LastException.InnerException
						: context.LastException;
		if (!excludedTypes.Contains(ex.GetType()))
		{
			InvokeNext(context);
		}
	}
}

What happens here is that any time an exception occurs, the first node in the exception handler chain is hit. This happens to be this ExceptionFilter class. It reads which exceptions should not go further down the chain from the configuration section. If the exception is not in the list of excluded types, it invokes the next item in the chain.

This type of programming (creating loosely coupled, highly cohesive objects) makes writing and extending code a breeze. Instead of changing existing tested code to filter the exceptions, I’m able to add new code. I think we can all agree that writing new code is better than mucking with existing code.

4 Comments

April Fools Day

I must be getting pretty crotchety in my old age, but I have had about all of the April Fools garbage that I can take.

From Microsoft’s Zune 180 to Google’s free wifi powered by your indoor plumbing… I mean come on. Is this stuff really that funny? The only thing that got a little smile from me was Python on Planes.

No Comments
flag
Favorite Charity
wounded warrior project
Search
Social
  • mattberther on twitter
  • mattberther on linkedin
Syndication
Archives
  • January 2010
  • September 2009
  • July 2009
  • June 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • September 2008
  • August 2008
  • June 2008
  • May 2008
  • April 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007
  • February 2007
  • January 2007
  • December 2006
  • November 2006
  • October 2006
  • September 2006
  • August 2006
  • July 2006
  • June 2006
  • May 2006
  • April 2006
  • March 2006
  • February 2006
  • January 2006
  • December 2005
  • November 2005
  • October 2005
  • September 2005
  • August 2005
  • July 2005
  • June 2005
  • May 2005
  • April 2005
  • March 2005
  • February 2005
  • January 2005
  • December 2004
  • November 2004
  • October 2004
  • September 2004
  • August 2004
  • July 2004
  • June 2004
  • May 2004
  • April 2004
  • March 2004
  • February 2004
  • January 2004
  • December 2003
  • November 2003
  • October 2003
  • September 2003
  • August 2003
  • July 2003
  • June 2003
  • May 2003
  • April 2003
  • March 2003
mattberther.com © 2003 - 2010