Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

2010-01-10

Spring.NET AOP - Behind The Scenes (3)

In the last installment of this series I showed you how you can leverage Spring.NET's ProxyFactory to wrap an object with a proxy and add interceptors to this proxy in order to enrich the behavior of your object's methods without having to changing a single line of code. Nevertheless it is quite cumbersome to wrap each single object explicitely.

Describing the "Where To Apply"

What we are looking for is a more automated approach, where we just want to describe the objects or - more fine grained - methods that we want to have a particular behavior applied. An interceptor ("Advice" in AOP terms) only describes *what* to do (e.g. retrying an operation), thus we need a way to describe *where* to apply it. In AOP terms, every method that can be wrapped by an interceptor is called a Joinpoint.

image

Of course we can taxatively enumerate the list of joinpoints that we want a particular advice to be applied like this:

Apply RetryInterceptor At
CalculatorWebService.Add
CalculatorWebService.Divide
...

but this clearly is not what we really want as in larger applications this quickly requires us to list each and every joinpoint in this list. What want to say something along the lines of

Apply RetryInterceptor At
All Service Methods

Looks much clearer, but how shall we describe that? You can compare it to selecting records from a database table. What we are dealing with here is a set of possible joinpoints and our "where" clause describes the characteristics of those joinpoints that we want to capture by our select statement. Applying this to our example, we can e.g. write

Apply RetryInterceptor At
ClassName LIKE '*Service' AND MethodName LIKE '*'

In AOP terms, such a SELECT statement, selecting a subset of joinpoints out of all possible joinpoints, is called a Pointcut.

image

Applying Advices to Pointcuts: Entering Object Post-Processors

Now that we have an idea, how we may select a set of joinpoints based on some criteria, how can we apply this technically? Remember, that in Spring you describe your objects using object definitions, a sort of recipe, that tells Spring how to instantiate and configure a particular object. Here's an example of such construction recipes in XML:

<object name="Alice" type="Spring.Objects.TestObject">           
<property name="age" value="31"/>
</object>

<object name="Bob" type="Spring.Objects.TestObject">
<property name="age" value="33"/>
<property name="spouse" ref="Alice" />
</object>

Using such object definitions we can build up whole object graphs, Since instantiation of these objects happens under control of Spring, we can leverage one of Spring's extension points to manipulate an object once it gets instantiated. This extension point is called "object post-processing". Everytime an object gets instantiated, Spring hands this object to all configured objects that implement the interface IObjectPostProcessor:

image

This is exactly what we need! We can implement our own IObjectPostProcessor to wrap the target instances within a proxy as needed. A simple implementation using a predicate for deciding which objects to wrap looks like this:

public class CustomAutoProxyCreator : IObjectPostProcessor
{
private readonly Func<object, string, bool> matchesPointcut;
private readonly IMethodInterceptor[] advices;

public CustomAutoProxyCreator(Func<object, string, bool> matchesPointcut,
                              params IMethodInterceptor[] advices)
{
  this.matchesPointcut = matchesPointcut;
  this.advices = advices;
}

public object PostProcessBeforeInitialization(object instance, string objectName)
{
  return instance;
}

public object PostProcessAfterInitialization(object instance, string objectName)
{
  if (matchesPointcut(instance, objectName))
  {
    ProxyFactory proxyFactory = new ProxyFactory(instance);
    foreach(var advice in advices)
    {
      proxyFactory.AddAdvice(advice);
    }
    return proxyFactory.GetProxy();
  }
  return instance;
}
}

We can now add this CustomAutoProxyCreator to our configuration in order to apply caching and retry behaviors to every object, who's object name ends with "*Service":

[Configuration]
public class AutoProxyDemoConfig
{
public CalculatorWebService TheCalculatorService()
{
  return new CalculatorWebService();
}

public CustomAutoProxyCreator AutoProxyCreator()
{
  return new CustomAutoProxyCreator(
      (instance, name) => name.EndsWith("Service"),
      new CacheInterceptor(), new RetryInterceptor()
  );
}
}

Reusing Spring.NET's AutoProxy Facilities - DefaultAdvisorAutoProxyCreator

Of course you don't need to implement your own IObjectPostProcessor for automatically creating AOP proxies. Spring.NET already comes with a predefined set of implementations that allow you to choose from various strategies for automatically creating proxies, DefaultAdvisorAutoProxyCreator (DAAPC) being the most flexible and powerful one.

What makes DAAPC so powerful? Remember our initial discussion about pointcuts and advices. DAAPC allows you to simply add such combinations of pointcuts and advices to the container configuration and will automatically pick them up to do it's magic. For this reason, Spring.NET introduced a special kind of object, a so called "Advisor". An advisor is nothing else than a combination of a pointcut and an advice to apply at this pointcut:

image

To leverage DAAPC, add a DAAPC and a list of advisors as needed to your container configuration. DAAPC then will automatically pickup these advisors and apply them. The following example demonstrates, how to apply our advices using this technique:

[Configuration]
public class DefaultAdvisorAutoProxyDemoConfig
{
public CalculatorWebService TheCalculatorService()
{
  return new CalculatorWebService();
}

public DefaultAdvisorAutoProxyCreator AutoProxyCreator()
{
  return new DefaultAdvisorAutoProxyCreator();
}

public DefaultPointcutAdvisor CacheServiceCallResultsAdvisor()
{
  return new DefaultPointcutAdvisor(
    new SdkRegularExpressionMethodPointcut(@".*Service\.*"),
    new CacheInterceptor()
  );
}

public DefaultPointcutAdvisor RetryServiceCallResultsAdvisor()
{
  return new DefaultPointcutAdvisor(
    new SdkRegularExpressionMethodPointcut(@".*Service\.*"),
    new RetryInterceptor()
  );
}
}

The advantage of this technique is, that whenever you want to apply a new advice, you just need to add new advisors to your definition and DAAPC automatically will pick them up and apply them.

And now the end is near...

What a journey. We started by identifiying cross-cutting concerns, refactoring them into separate classes using the decorator pattern. By introducing interceptors we made those behaviors reusable across different target classes. Using ProxyFactory, we even don't have to write any proxy code anymore. Finally, using pointcuts and Spring.NET's AutoProxy facilities, we can easily apply advices on any set of objects as needed. By following common sense and step-by-step refactoring, we almost naturally ended up at this mysterious technique called Aspect-Oriented Programming and proofs that there is nothing magically behind this concept. Also it proofs, that Object-Oriented Programming and Aspect-Oriented Programming are not mutually exclusive, but perfectly work together to tame today's application's complexities.

Nevertheless we are not done yet. Until now we have only discussed the technical solution, how to implement AOP. In my next post I will discuss, when to use AOP and point out a couple of issues you have to consider when applying AOP.

As usual, you can download the sample code for this post.

2010-01-04

Spring. NET AOP - behind the scenes (2)

This is the second installment of my series about the internals of Spring.NET AOP. In my first post of this series I described the first step in separating concerns and how we can use the decorator pattern to make our code much better maintainable. Nevertheless we were still left with two major problems:

  • Changing an interface to our service requires all decorators to be changed
  • Lack of reusing decorator logic for other services

A more generic approach: Interceptors

As mentioned, we can do better. Assume we have other services in our application. We do not want to implement the caching or retry code each time and for every method. Code duplication is the root of all evil. Thus we need to improve our solution. First, let's refactor our retry code into a separate class, that can be used to wrap any arbitrary method call. We will introduce a special interface for these added behaviors and call them interceptors:

public interface IMethodInterceptor
{
 object InvokeMethod(Func<object> invokeNext);
}

An interceptor implementation gets passed in a delegate. This delegate can either be the method we are wrapping or even another interceptor. The method we are wrapping is usually called the target method. When the delegate is another interceptor, we refer to this as an interceptor chain, with each interceptor adding its own behavior before calling the target method. Our Retry-interceptor then looks like this:

public class RetryInterceptor : IMethodInterceptor
{
 public object InvokeMethod(Func<object> invokeNext)
 {
   int retries = 0;
   while (true)
   {
     try
     {
       return invokeNext();
     }
     catch (Exception ex)
     {
       retries++;
       if (retries >= 3)
       {
         throw; // retry threshold exceeded, giving up
       }
       Thread.Sleep(1000); // wait a second
     }
   }
 }
}

Notice, that our RetryInterceptor now is absolutely unaware of the target method or its arguments. It just gets passed in a delegate to invoke, which hands over control to either the next interceptor in the chain or the actual target method.

Now we can implement our interceptor chain in a rather generic way, we will call it our CalculatorProxy and hand it our actual target instance and a list of interceptors. The actual method invocation is a bit tricky, but doable:

public class CalculatorProxy : ICalculator
{
 private ICalculator target;
 private IMethodInterceptor[] interceptors;

 public CalculatorProxy(ICalculator target, IMethodInterceptor[] interceptors)
 {
   this.target = target;
   this.interceptors = interceptors;
 }

 public int Add(int x, int y)
 {
   return (int) InvokeInterceptorAtIndex(0, ()=>target.Add(x, y));
 }

 private object InvokeInterceptorAtIndex(int interceptorIndex, Func<object> targetMethod)
 {
   if (interceptorIndex >= interceptors.Length)
   {
     return targetMethod();
   }
   return interceptors[interceptorIndex].InvokeMethod(
           () => InvokeInterceptorAtIndex(interceptorIndex + 1, targetMethod)
       );
 }
}

This proxy implementation accepts calls coming in over the ICalculator.Add() interface method and passes control to the first interceptor in the chain. Initialize our proxy like this:

ICalculator calc = new CalculatorProxy(
                       new CalculatorWebService(),
                       new IMethodInterceptor[] { new RetryInterceptor() });
int sum = calc.Add(2, 5);

Each interceptor will invoke the next interceptor in the list if available or the final target:

calculatorproxy_callgraph

We have just implemented a mechanism that allows us to add any arbitrary number of interceptors to our proxy!

Generating Proxies - Spring's ProxyFactory

Of course we implemented our interception mechanism for one method only yet. Assume we have to extend the capabilities of our remote calculator and add a new Divide() method. How would the proxy implementation of this method look like? Look at this:

public double Divide(double dividend, double divisor)
{
 return (int)InvokeNext(0, () => target.Divide(dividend, divisor));
}

Comparing this implementation to our previous Add() implementation, the pattern becomes obvious. Both methods hand control to the first interceptor and pass in a delegate to the actual method invocation. No matter how many methods we add, this code will always look the same. Let's refactor the common code for invoking the interceptor chain into a base class AbstractProxy:

public abstract class AbstractProxy
{
 private IMethodInterceptor[] interceptors;

 public AbstractProxy(IMethodInterceptor[] interceptors)
 {
   this.interceptors = interceptors;
 }

 protected object InvokeInterceptorAtIndex(int interceptorIndex, Func<object> targetMethod)
 {
   if (interceptorIndex >= interceptors.Length)
   {
     return targetMethod();
   }
   return interceptors[interceptorIndex].InvokeMethod(
       () => InvokeInterceptorAtIndex(interceptorIndex + 1, targetMethod)
     );
 }
}

Our CalculatorProxy then will be:

public class CalculatorProxy : AbstractProxy, ICalculator
{
 private readonly ICalculator target;

 public CalculatorProxy(ICalculator target, IMethodInterceptor[] interceptors)
   : base(interceptors)
 {
   this.target = target;
 }

 public int Add(int x, int y)
 {
   return (int)InvokeInterceptorAtIndex(0, () => target.Add(x, y));
 }

 public double Divide(double dividend, double divisor)
 {
   return (int)InvokeInterceptorAtIndex(0, () => target.Divide(dividend, divisor));
 }
}

Even if we implemented other interfaces, these lines would be the same. Luckily, Castle.DynamicProxy, LinFu and of course Spring.NET come with mechanisms that allow this code to be generated at runtime. Below I will show you, how you can use Spring.NET's ProxyFactory to automatically generate this proxy code.

First, to make our interceptor compatible to Spring.NET, we need to implement Spring.NET's IMethodInterceptor interface for our interceptors (instead of our own IMethodInterceptor interface as described above):

public class RetryInterceptor : IMethodInterceptor // Spring.NET's interceptor interface!
{
 public object Invoke(IMethodInvocation invocation)
 {
   int retries = 0;
   while (true)
   {
     try
     {
       return invocation.Proceed();
     }
     catch (Exception ex)
     {
       retries++;
       if (retries >= 3)
       {
         throw; // retry threshold exceeded, giving up
       }
       Thread.Sleep(1000); // wait a second
     }
   }
 }
}

Notice, that instead of getting passed in a method delegate, Spring.NET's IMethodInterceptor.Invoke() receives an instance of IMethodInvocation and calls Proceed() to hand control to the next interceptor or target method in the chain. In contrast to the simple delegate that we used in our manually coded proxy, the IMethodInvocation interface allows you to access additional information about the current method call:

public interface IMethodInvocation
{
 /// <summary>
 /// Get the proxy instance for the current method invocation
 /// </summary>
 object Proxy { get; }
 /// <summary>
 /// Get the target instance for the current method invocation
 /// </summary>
 object Target { get; }
 /// <summary>
 /// Get the method info for the current method invocation
 /// </summary>
 MethodInfo Method { get; }
 /// <summary>
 /// Get the arguments for the current method invocation
 /// </summary>
 object[] Arguments { get; }
 /// <summary>
 /// Hand control to next interceptor or target
 /// </summary>
 object Proceed();
}

Now that we have our interceptors ready, we can use Spring.NET's ProxyFactory to have the proxy class automatically generated for us. Note, that in the example below the method used to add an interceptor is called "AddAdvice". Advice is the common term to refer to an action to be taken before or after calling the actual target. For a more detailled description of common AOP terminology, please refer to the Spring.NET AOP reference. Here's the code to let Spring.NET generate such a proxy instance for us:

ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.Target = new CalculatorWebService(); // set target
proxyFactory.AddAdvice( new RetryInterceptor() ); // add interceptor

ICalculator calc = (ICalculator) proxyFactory.GetProxy(); // create proxy instance

The call to GetProxy() will generate a proxy instance, set the target and add the list of interceptors to the proxy. The result is the same structure we showed above and also the call graph of an interceptor chain looks very familiar:

calculatorproxyfactory_callgraph

The difference is, that we didn't have to write a single line of code for our proxy. This means that we now easily can reuse our RetryInterceptor across all kinds of classes in our application!

We want more!

Wow, what a journey. We started by separating concerns into their own classes by applying the decorator pattern, implemented our own proxy with a flexible method interception mechanism and finally saw, how Spring.NET's ProxyFactory can be used to do all of this for us automatically.

Is there anything left on our wishlist? Imagine we have a whole bunch of Service classes in our application that we would like to retry their operations. We'd have to execute the lines to create the proxy, set the target and add the interceptors for each service individually. What about a feature that allows you to just point to a list of objects and tell Spring.NET to wrap those objects in a proxy with a given list of interceptors?

Indeed the AOP framework of Spring.NET comes with a great feature called "AutoProxying" that makes it easy to automatically apply interceptors to a set of objects. Stay tuned to read how this feature works in the next post of this series!

As usual you can download the example code.

2009-12-28

Spring.NET AOP - behind the scenes (1)

On the forums I see one topic coming up quite often: "Can I advise XY?". In this multipart post series I will describe the motivation for AOP and the way Spring.NET AOP (and most others like Castle.DynamicProxy and LinFu) technically work in .NET to give you a better understanding and provide you the knowledge to help answering such questions yourself.

The example: Retrying operations

Instead of the usual logging example I'd like to show you another useful feature: Retrying operations. For the sake of simplicity let's assume we're calling a webservice method for calculating the sum of two integers.

CalculatorWebService calc = new CalculatorWebService("http:/...");
int sum = calc.Add(2, 5);

Since webservices usually involve calling over the network, they are inherently unsafe and might fail for various reasons. In our application, we would like to retry webservice operations 3 times before giving up, with a 1 second delay between retries.

There are a couple of ways to implement this requirement, the most direct approach probably by deriving our own class from the webservice client class:

public class RetryingCalculatorWebService : CalculatorWebService
{
  public RetryingCalculatorWebService(string url):base(url) {}   

  public override int Add(int x, int y)
  {
    int retries = 0;
    while (true)
    {
      try
      {
        return base.Add(x, y);
      }
      catch (Exception ex)
      {
        retries++;
        if (retries >= 3)
        {
          throw; // retry threshold exceeded, giving up// wait a second
      }
    }
  }
}

There are of course a couple of issues with that approach, the 2 most important are:

  • The code for retrying the operation effectively buries our single line of actual business code. This makes it hard identifying what the code actually does:
public class RetryingCalculatorWebService : CalculatorWebService
{
  public RetryingCalculatorWebService(string url):base(url) {}   

  public override int Add(int x, int y)
  {
    int retries = 0;
    while(true)
    {
      try
      {
        return base.Add(x, y);
      }
      catch(Exception ex)
      {
        retries++;
        if (retries >= 3)
        {
          throw; // retry threshold exceeded, giving up
        }
        Thread.Sleep(1000); // wait a second
      }
    }
  }
}
  • When implementing this requirement across all our webservice clients we not only end up scattering the same lines of code all over our codebase. A change in the requirement might cause us having to change all our webservice client classes causing a huge amount of work.

image

A manually implemented a solution

A structured way for non-intrusively adding behavior to exisiting code is described in the GoF book, the pattern is called "Decorator", the basic idea being wrapping the actual target method with additional code. Thus you do not need to modify any existing code, instead you "chain" the various required behaviours, each behaviour implemented in its own class. In contrast to the GoF-pattern, nowadays composition is favoured over inheritance, thus instead of using the inheritance approach, let's introduce an interface to easily chain our behaviors:

public interface ICalculator
{
  int Add(int x, int y);
}
ICalculator calc = ...;
int sum = calc.Add(2, 5);

Now we can easily implement our business logic and the infrastructure constraint separately and chain them later as needed:

public class CalculatorWebService : ICalculator
{
  public CalculatorWebService(string url) { ... }   

  public int Add(int x, int y)
  {
    // perform actual webservice call
    return ...
  }
}
public class CalculatorRetryDecorator : ICalculator
{
  private ICalculator next;

  public CalculatorRetryDecorator(ICalculator next) { this.next = next; }

  public int Add(int x, int y)
  {
    int retries = 0;
    while (true)
    {
      try
      {
        return next.Add(x, y);
      }
      catch (Exception ex)
      {
        retries++;
        if (retries >= 3)
        {
          throw; // retry threshold exceeded, giving up
        }
        Thread.Sleep(1000); // wait a second
      }
    }
  }
}

Notice how the CalculatorRetryDecorator delegates the actual work to the next calculator in the chain. Now, whenever our requirements force us to retry calculator operations, we just "chain" the implementations together:

ICalculator calc = new CalculatorRetryDecorator( new CalculatorWebService( "http://..." ) );
int sum = calc.Add(2, 5);

Now, when we discover that our performance is to slow, well - implement a caching decorator that caches method results for a certain amount of time using the same approach and add it to the decorator chain:

ICalculator calc = new CalculatorCacheDecorator( new CalculatorRetryDecorator( new CalculatorWebService( "http://..." ) ) );
int sum = calc.Add(2, 5);

When we call the Add() method,  our call graph looks like this:

calculatordecorator_callgraph

This is only the beginning

We already achieved a lot by separating concerns into different classes. Still our solution has some significant weaknesses:

  • When we add new methods to our ICalculator, we need to extend all of our decorators
  • We want to reuse the retry logic for other services

In my next post I will address those issues and show you how we can implement a more generic solution.

Here you can download the example code for this post.

2009-12-24

A little Christmas present - for .NET

Just read Eberhard Wolff's newest blog post and simply couldn't resist to borrow the idea and show you, how the same things can be done using Spring.NET. First, here's the .NET version of Eberhard's example:

public class MyRepository
{ }

public class MyService
{
    public MyRepository MyRepository { get; set; }
}

Here it is, the smallest possible Spring.NET object. Notice, due to Java's lack of properties the .NET version is even smaller. Still, no attributes, no Spring dependencies - pure code.

How do you wire them? Spring.NET's XML configuration unfortunately lacks Spring.Java's component-scanning as demonstrated in Eberhard's post. But using the new code-based configuration I presented recently, you easily can wire your objects by writing

appContext.Configure(cfg => cfg
     .Scan(scan => scan
        .TheCallingAssembly()
        .Include(t => t.FullName.EndsWith("Service") || t.FullName.EndsWith("Repository"))
        .With<AutowiringConvention>()
));

The example code can be downloaded at SmallestSpringObject.zip

Merry Christmas!

2009-12-21

NetMX & Spring.NET - configure your Apps at runtime

Ever wished you could change some settings of your application during runtime? Easily retrieve runtime information from your components? You tried WMI and Performance Counters?

Well I did and to put it polite: I don't like WMI. Performance Counters are a nice way to retrieve peformance information about an application, but when it comes to changing an application's settings or behavior at runtime, you need another way. WMI is still COM-based, although a WMI.NET binding is available via the System.Management components. Alas this binding is not complete and functions are spread across different namespaces for historical reasons. To put a long story short: It is nothing for the fainthearted.

Brief Introduction to Java Management Extensions (JMX)

In the Java universe for this purpose there is JMX. Basically it allows an application to expose management objects via a JMX server. A monitoring client can then connect to this server and dynamically obtain runtime information about the exposed management objects. In contrast to WMI there is no schema involved, everything is discovered dynamically. For instance the server application could expose the following management bean:

public interface SampleMBean
{
    public String getHello();
    public void setHello(String helloMessage);
    public String sayHello();
}

public class Sample implements SampleMBean {

    private String hello = "Hello World(s)!";

    public Sample() {
    }

    public String getHello() {
        return hello;
    }

    public void setHello(String helloMessage) {
      hello = helloMessage;
    }

    public String sayHello() {
      return hello;
    }
}

Using the JConsole tool, one can easily connect to this application's virtual machine and remotely retrieve/change the properties as well as invoke the exposed method(s):

image

 image

The server application may expose its management objects over a variety of different connectors, as it is shown in this image (copied from the Wikipedia article about JMX)

And Now: .NET Management Extensions

Thanks to the amazing work of Szymon Pobiega, the power of JMX is available for the .NET platform as well. The NetMX implementation is available from CodePlex. The really nice part is, that it also comes with a working implementation of the JSR262 JMX connector, so that it is possible to connect to your .NET application using JConsole (yes, that's true and I'm going to proof that ;-)). Of course NetMX also comes with a .NET version of the console, please check out the project for more. I grabbed the sources and compiled them. After playing around a while, I decided to implement a simple usage scenario.

The Sample Scenario

Every now and then I wanted to increase decrease the logging level of my applications (among other things ...). Using NetMX it should be easy. And - well it was! Using Spring.NET, it was easy to weave a logging advice around my components, using NetMX it was easy to expose a management object for this logging advice, so that the log settings can be changed at runtime. The picture below illustrates the scenario setup I aimed for:

image The Logging Advice intercepts every call to the service object and logs the method calls to the log system. By default, logging is turned off, using JConsole I want to change those settings during runtime.

My sample application again is the MovieFinder application. To make the effect visible, the client code retrieves the movielist every second and prints the timestamp + the moviename on the console. Also the logging system is configured to write to the console, but disabled by default.

The Solution

The sources for my experiment can be fetched from my subversion repository. What you also need is the JSR262 enhanced version of JConsole, which is included in the samples of the JSR262 Connector download. Unpack the connector download and checkout $/jsr262-ri-ea4/samples/index.html for more.

So launching the application results in a screen similar to this:

image

Now launch JConsole and connect to our .NET application using the url "service:jmx:ws://127.0.0.1:9998/jmxws":

imageExpanding the tree shown in the left pane, you should see this:

image  Now let's change some settings. Double-Click into the "Value" column and enter the following:

imageé voila! Our console has significantly changed now:

image

We just reconfigured the logging advice on the fly to also log all method calls to our service and also dumps the arguments passed in!

Here's the configuration snipped required to make this happen (using Spring.NET CodeConfig from my last post):

var appContext = new GenericApplicationContext(false);
appContext.Configure()
   .FromConfiguration<MovieFinderConfiguration>()
    .EnableLogging(log =>
    {
       log.TypeFilter = type => type.IsDefined(typeof(ServiceAttribute), true);
       log.Logger.LogLevel = LogLevel.Off;
    })
   .EnableNetMX(netmx =>
   {
     netmx.AddConnector<Jsr262ConnectorServerProvider>(new Uri("http://0.0.0.0:9998/jmxws"));
     netmx.ExportMBean<SimpleLoggingManager>();
   });

Enjoy and again thanks to Szymon for his great work!

2009-12-17

Merry XMLless! CodeConfig for Spring.NET

Straight to the point: XML is not meant for humans. Fullstop. The only way for humans to deal with XML is when it is hidden behind proper tooling support. Without a tool hiding XAML you wouldn't write XAML code by hand, would you? Currently being on a greenfield project with my team collegues not familar with Spring.NET it quickly turned out that XML configuration can be quite a hurdle, burying the gain of power in the pain of configuration. Using the simple MovieFinder example from the Spring.NET quickstart examples, I would like to introduce you to a new way to do familar things.

Introducing MovieFinder

In the following I will use the following - very simple - example to show you different ways of wiring the components. A MovieLister can be used to obtain a list of movies directed by a particular director. To access persistent storage, it uses the MovieFinder repository component: sample

Here's how the client code might look like:

IMovieLister lister = ...
var movies = lister.MoviesDirectedBy("Roberto Benigni")

The traditional way of wiring

The traditional way of configuring the Spring.NET container looks like this:

<objects xmlns='http://www.springframework.net'>

  <object id='movieLister' type='MovieFinder.Core.MovieLister, MovieFinder.Core'>
    <constructor-arg index='0' ref='movieFinder' />
  </object>
  
  <object id='movieFinder' type ='MovieFinder.Data.SimpleMovieFinder, MovieFinder.Data' />    
  
</objects>
Code Example: Traditional Configuration

There are a couple of problems with that approach, here are some:

  • not pleasant to read
  • much 'noise', xml syntax hiding the actual wiring structure
  • lack of refactoring support
  • unmanageable for large object numbers

You can imagine that in large applications without any tool support this can be become very painful. Already less known is the fact that Spring is able to autowire components. Here's the example to autowire components based on type-matching contructor arguments (see the reference documentation for other values of 'default-autowire'):

<objects xmlns='http://www.springframework.net' default-autowire='constructor'>

  <object id='movieLister' type='MovieFinder.Core.MovieLister, MovieFinder.Core' />  
  <object id='movieFinder' type ='MovieFinder.Data.SimpleMovieFinder, MovieFinder.Data' />    
  
</objects>
Code Example: Using constructor autwiring

This saves you from having to manually specifiying all dependencies. Of course, renaming your classes still may break this configuration.

Mark Pollack blogged an extensive post about configuring the Spring.NET container, including the even less known container API for configuring the container.

Going fluent

A lot of frameworks out there have already introduced a configuration style known as fluent API. A nice example for the Windsor container can be found here. There's a lot more, Fluent NHibernate being another very populare example.

Recently, Tom Farnbauer released such a fluent configuration API for Spring.NET, Recoil for Spring.NET. Using Recoil, our MovieFinder example could look like this:

public class MyWiringContainer : WiringContainer
{
    public override void SetupContainer()
    {
        Define( () => new MovieFinder() )
             .As<IMovieFinder>;

        Define( () => new MovieLister( Wire<IMovieFinder>() ) )
             .As<IMovieLister>;
    }
} var myContext = new GenericApplicationContext(); myContext.Configure() .With<MyWiringContainer>(); myContext.Refresh();
Code Example: Wiring using Recoil for Spring.NET

Unfortunately I quickly found while introducing Recoil into my current project, that the API has some flaws and - after all - when looking at fluent apis, they usually add as much codenoise to your configuration as xml already does. Also fluent APIs tend to be less extensible than other approaches. Imho Fluent NHibernate suffers this fate a lot (probably others too, but this is the latest example crossing my way).

Of course we already achieved at least 1 important goal: We are safe against refactoring. Any class moves or renames will automatically be reflected in our configuration - because it is code.

Back to the whiteboard

I didn't find any of those approaches really satisfying. After all, all I want to do is

var movieFinder = new MovieFinder();
var movieLister = new MovieLister( movieFinder );

So lets start with the least minimal configuration container I can think of. A simple class, who's member methods return the objects you are asking for:

public class MovieFinderConfiguration 
{
   public IMovieFinder MovieFinder() 
  {
     return new MovieFinder();
  }

  public IMovieLister MovieLister()
  {
    return new MovieLister( MovieFinder() )
  }
}
Code Example: Wiring using ... plain C#

This already does a lot of what we want:

  • it is readable
  • it doesn't cause more codenoise than your standard code would have
  • we have full refactoring support
  • we automatically get the whole object graph once we call MovieLister():
var container = new MovieFinderConfiguration();
var movieLister = container.MovieLister();
var movies = movieLister.MoviesDirectedBy("Roberto Bergnini");
Code Example: Obtaining the object graph from our C# "container"

Unfortunately our minimal container is lacking a couple of things:

  • no support for managing the object lifecycle - everytime we call MovieLister() it will return a new graph
  • no support for applying aspects to care for crosscutting concerns
  • no support for all the other features you get from the containers out there

New on stage: CodeConfig for Spring.NET

Rooting in a great idea of Rod Johnson, Chris Beams started working on bringing this idea to the Java world, the result is JavaConfig (and since yesterday's release of our mother-project integral part of Spring 3.0, congrats at this point to the Java team!). Mark Pollack implemented the first POC for Spring.NET, due to the needs in my current project, I decided to take that POC and continue develop it.

Yet again, Spring.NET surprised me. Due to being incredibly flexible, it was almost a breeze to merge the above mentioned concept with the container infrastructure. How does our MovieFinder look like using CodeConfig? Simple:

[Configuration]
public class MovieFinderConfiguration 
{
   public virtual IMovieFinder MovieFinder() 
  {
     return new MovieFinder();
  }

  public virtual IMovieLister MovieLister()
  {
    return new MovieLister( MovieFinder() )
  }
}
Code Example: The CodeConfig configuration - not much difference!

Note the additional [Configuration] attribute and the "virtual" keyword added to the methods. Now feed this configuration into the Spring.NET application context and retrieve an instance of the IMovieLister:

var appContext = new GenericApplicationContext();
appContext.Configure()
    .FromConfiguration<MovieFinderConfiguration>();
ApplicationContext.Refresh();

var movieLister = appContext.GetObject<IMovieLister>();
var movies = movieLister.MoviesDirectedBy("Roberto Bergnini");
Code Example: retrieving an IMovieFinder from an CodeConfig-configured application context

Neat, isn't it? This means you can write your configuration in the simplest possible way and still can leverage the full power of the IoC container. Enabling logging on your services? No problem:

appContext.Configure() 
.FromConfiguration<MovieFinderConfiguration>()
.EnableLogging(cfg => { cfg.TypeFilter = type => type.IsDefined(typeof(ServiceAttribute), true); cfg.Logger.LogExecutionTime = true; cfg.Logger.LogMethodArguments = true; cfg.Logger.LogReturnValue = true; cfg.Logger.LogLevel = LogLevel.Trace; });

Using Conventions for Configuration

You don't want to configure each object manually in a large application? Use component-scanning, a feature that I shamelessly stole from StructureMap:

appContext.Configure() 
    .Scan(s => s                
        .AssemblyOfType<MovieLister>()
        .AssemblyOfType<SimpleMovieFinder>()
        .Include(t => t.IsDefined(typeof (ComponentAttribute), true))
        .With<TypeNamingConvention>()
        .With<AutowiringConvention>()
    );

Sources, Documentation and Next Steps

At this moment, you can find the sources in my public SVN repository at XP-Dev. Note, that the code will move to SpringSource's CodeConfig for Spring.NET repository here at a later stage.

For a quick overview of what is already possible, check out the various configuration examples for the MovieFinder example there. Documentation is missing, but reading the JavaConfig reference will give you a good overview of the features. For the component-scanning feature read Jeremy Miller's introduction on assembly scanning.

Beware that this is still a moving target, consider it not being more than a preview yet. But I'd love you to grab the sources, play around and let me know what you think - keen on hearing your feedback!

The first milestone of CodeConfig is scheduled for end of January - and don't forget to check, later this day, Spring.NET 1.3.0 GA will be released.

Merry XMLless!

2009-08-06

Spring for .NET 1.3.0 Release Candidate available

Finally we made it: The next release of Spring for .NET is available for preview and brings a couple of new things as well as over 100 fixed bugs to the table. Grab the new release as usual from our website http://www.springframework.net and give it a test run. The final release is currently scheduled for the first week in September. Below I will give you a short introduction to the new features.

New Features

NVelocity Support

Erez Mazor joined the team in June and brought a nice integration of the NVelocity template library (part of the Castle project) with him. Let's asume you need to send a confirmation email after processing T-Shirt order to a customer. Most of this email will come from a template, just a few variables will be individual for each customer. Here's how such a template looks like using the Velocity Template Language: 

Dear#if ($sex == "F") Ms#else Mr#end $recipient,
 
We are happy to withdraw $1Mio from your account

Here's an example on how to use Spring.NET's integration to send an Email from your application. The configuration causes the NVelocityFactory to load templates from the NVelocityDemo assembly's "NVelocityDemo" namespace:

<objects xmlns="http://www.springframework.net" xmlns:nv="http://www.springframework.net/nvelocity">
  <nv:engine id="velocityEngine">
    <nv:resource-loader>
      <nv:spring uri="assembly://NVelocityDemo/NVelocityDemo/"/>
    </nv:resource-loader>
  </nv:engine>
 
  <object id="emailSendService" type="NVelocityDemo.EmailSendService">
    <property name="VelocityEngine" ref="velocityEngine" />
  </object>
</objects>

Here's the C# Code of my EmailSendService class:

public class EmailSendService
{
  public VelocityEngine VelocityEngine { get; private set; }

  public void SendEmail(string recipientName, string sex, string emailAddress, string subject)
  {
    Hashtable model = new Hashtable();
    model["email"] = emailAddress;
    model["recipient"] = recipientName;
    model["sex"] = sex;
    IContext modelContext = new VelocityContext(model);
    StringWriter sw = new StringWriter();
    this.VelocityEngine.MergeTemplate("confirmationEmail.vm", Encoding.UTF8.HeaderName, modelContext, sw);

    string emailContent = sw.ToString();

    // send mail
    Console.WriteLine("Sending email to {0} with subject '{1}':\n{2}", emailAddress, subject, emailContent);
  }
}

Running this example will inform our customer about our pricing for T-Shirts:

Sending email to foo@world.com with subject 'Thank you!':
Dear Mr Smith,

we are happy to withdraw $1Mio from your account
TIBCO Enterprise Message Service

Similar to our support for MSMQ and ActiveMQ, consequently there is now also support for Tibco's EMS. If you are already familiar with Spring's ActiveMQ support, you will quickly feel comfortable. To get started, check out our reference documentation and the upcoming blog post at Mark Pollack's Blog.

MS Test

Some of us are forced to write their unit tests using Microsoft's own testing framework. To support them, Spring.NET now also integrates support for writing unit and integration tests similar to the one already available for NUnit. You can find the supporting stuff in the Spring.Testing.Microsoft assembly.

Noteworthy Improvements

Testing

In response to a lot of requests, we upgraded our NUnit testing environment to the latest NUnit 2.5.1. There is also new support for writing database integration tests. Use the SimpleAdoTestUtils class to execute arbitrary SQL scripts to setup/teardown your database. An example is Spring's NHibernate Integration tests. Here is the SQL script to recreate our integration database:

IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'Spring')
BEGIN
    ALTER DATABASE Spring 
        SET SINGLE_USER 
        WITH ROLLBACK IMMEDIATE

    DROP DATABASE Spring
END
GO

IF  EXISTS (SELECT * FROM sys.server_principals WHERE name = N'springqa2')
    DROP LOGIN [springqa2]
GO

CREATE DATABASE Spring
GO

CREATE LOGIN [springqa2] WITH PASSWORD=N'springqa2', DEFAULT_DATABASE=[Spring], DEFAULT_LANGUAGE=[us_english]
GO

USE Spring
CREATE USER [springqa2] FOR LOGIN [springqa2] WITH DEFAULT_SCHEMA=[dbo]
EXEC sp_addrolemember 'db_owner', 'springqa2'
GO

Now, leveraging NUnit's [SetupFixture] feature, we can easily execute this and other scripts before the execution of each fixture:

[SetUpFixture]
public class Setup
{
  private const string DBConnection = "Data Source=SPRINGQA;Database=$DATABASE$;Trusted_Connection=False;User ID=springqa;Password=springqa";
  private readonly IResourceLoader resourceLoader = new ConfigurableResourceLoader();

  private IResource GetResource(object instance, string name)
  {
    string resourcePath = TestResourceLoader.GetAssemblyResourceUri(instance, name);
    return resourceLoader.GetResource(resourcePath);
  }

  [SetUp]
  public void InstallMSSQLDatabase()
  {
    IDbProvider dbProvider = DbProviderFactory.GetDbProvider("SqlServer-2.0");
    AdoTemplate ado = new AdoTemplate(dbProvider);

    // (re-)create database(s)
    dbProvider.ConnectionString = DBConnection.Replace("$DATABASE$", "master");
    SimpleAdoTestUtils.ExecuteSqlScript(ado, GetResource(this, "RecreateDatabases.sql"));

    // create tables
    dbProvider.ConnectionString = DBConnection.Replace("$DATABASE$", "Spring");
    SimpleAdoTestUtils.ExecuteSqlScript(ado, GetResource(this, "Data.NHibernate/creditdebit.sql"));
    SimpleAdoTestUtils.ExecuteSqlScript(ado, GetResource(this, "Data.NHibernate/testObject.sql"));
  }
}

Using the new NVelocity integration, you could even easily parameterize your SQL scripts for different environments.

Configuration Error Handling

Previously sometimes it was hard to read configuration errors. I put some effort into reducing this pain and make the error messages much more explicit. Now you get the exact filename + linenumber of the offending object definition and also a more detailled explanation, what is causing the problem.

AOP Performance

The performance of AOP proxies at runtime improved, but also *creating* such singleton proxies at startup time could cause some issues. You now get a bunch of different Auto-Proxy processor implementations to choose from to better suite your exact needs.

Sometimes using <tx:attribute-driven /> or <aop:config> could cause issues when an additional XXXAutoProxyCreator was defined in your configuration. This roots in the fact that those 2 configuration elements silently registered their own DefaultAutoProxyCreator under the hoods. This is now taken care of and it is guaranteed that infrastructure AOP elements will not interfere with user-defined ones anymore.

Feedback welcome

The release will be in ~ 3-4 weeks, so please grab a copy of the release candidate and give it a whirl - We'd be happy to get your feedback!