I say.

A blog by Joakim Beijar, I solve interesting and mundane problems at HappySignals and hack at night on github.com/kaa.

Custom ResourceLoaders in NVelocity

09 Sep 2008

I needed a custom resource loader for NVelocity to enable me to unit test my new NVelocityView for the ASP.NET MVC app I was building. I studied some examples and went to work. Easy-peasy, I soon had a MemoryResourceLoader that loaded that looked something like this:

public class MemoryResourceLoader : ResourceLoader {
  static IDictionary templates = new Dictionary();
  public static IDictionary Templates { get { return templates; } }
  public static void AddTemplate(string name, string template) {
    templates[name] = Encoding.UTF8.GetBytes(template);
  } 		
public override Stream GetResourceStream(string template) { byte[] templateBytes; if(!templates.TryGetValue( template, out templateBytes)) { throw new ResourceNotFoundException(
"MemoryResourceLoader Error: cannot find resource " + template); } return new MemoryStream(templateBytes); } public override void Init(ExtendedProperties configuration) {} public override long GetLastModified(Resource resource) {
return 0;
} public override bool IsSourceModified(Resource resource) {
return false;
} }

Which I tried to get NVelocity to use by going:

VelocityEngine engine = new VelocityEngine();
ExtendedProperties properties = new ExtendedProperties();
properties.AddProperty("resource.loader", "memory");
properties.AddProperty(
"memory.resource.loader.class",
"NVelocityView.MemoryResourceLoader;NVelocityView");
engine.Init(properties);

But no! All I got was:

Problem initializing template loader: NVelocityView.MemoryResourceLoader
Error is: System.ArgumentNullException: Value cannot be null.
Parameter name: type

I threw Process Monitor at it trying to figure out if it was looking for my assembly in a bisarre place, I tried fuslogvw.exe to see if there was a problem loading the assembly, I debugged and couldn’t find a solution. Until I decompiled with Reflector and noticed the somewhat strange line

loaderClassName = loaderClassName.Replace(';', ','); 

in the decompiled source. Why would someone use ';' in a type reference? Someone porting from Java of course with some strange configuration framework that uses ',' as a separator between values of course! As soon as I switched ',' to ';' in the initialization code it was all dandy again.