Castle.Windsor and lifecycle of objects

In a previous post I discuss about the importance of calling IWindsorContainer.Release() for all object created through Windsor, to avoid memory leak. There is a little correction to do, the container keeps a reference to an object created through Resolve<T> only if that object implements IDisposable. But it is important to really understand the concept of lifecycle of objects in Windsor. Suppose you have an object that implements IDisposable and tells if it was disposed with a simple property called aProperty

public class DisposableTest : ITest {
   
public static Int32 NumOfDispose = 0;
 
   
private byte[] big = new byte[1000000];
 
   #region IDisposable Members
 
   
public Boolean aProperty = false;
 
   
public void Dispose() {
      aProperty = 
true;
      NumOfDispose++;
   }
 
   #endregion
 
   #region ITest Members
 
   
public bool AProperty {
      
get { return aProperty; }
   }
 
   #endregion
}

now configure two component in the config file, one with transient lifecycle and another with singleton lifecycle, this test shows you an important concept

ITest tran, sing;
using (WindsorContainer ioc = new WindsorContainer(new XmlInterpreter(“config1.xml”))) {
   tran = ioc.Resolve<
ITest>(“TransientITest”);
   sing = ioc.Resolve<
ITest>(“SingletonITest”);
}
Assert.IsTrue(tran.AProperty);
Assert.IsTrue(sing.AProperty);

After the container is disposed, it disposes also all transient and singleton objects created with resolve. This is the reason why the container keeps references to transient objects that implement IDisposable. So do not remember to call Resolve for all transient object that are IDisposable if you do not dispose the container itself. Now you can do another test.

using (WindsorContainer ioc = new WindsorContainer(new XmlInterpreter(“config1.xml”))) {
   tran = ioc.Resolve<
ITest>(“TransientITest”);
   sing1 = ioc.Resolve<
ITest>(“SingletonITest”);
   ioc.Release(tran);
   ioc.Release(sing1);
   
Assert.IsTrue(tran.AProperty);
   
Assert.IsFalse(sing1.AProperty);
   sing2 = ioc.Resolve<
ITest>(“SingletonITest”);
   
Assert.AreSame(sing1, sing2);
}

This test shows two distinct things: if you call WindsorContainer.Release only the transient objects gets their Dispose method called, not the singleton one. Moreover, even if you call release on the singleton object, the object gets no removed from the container, if you resolve again, the instance returned is the same as before. So a singleton object lifecycle spans the life of the container, even if the user explicitly calls Release on it. Now to finish this example lets create another class and configure as transient

public class DisposableCon : IDisposable {
 
   
public ITest ITest;
 
   
public DisposableCon(ITest iTest) {
      ITest = iTest;
   }
 
   
public void Dispose() {
 
   }
 }

This class simply declare a Constructor dependency, and implements IDisposable, but in the dispose does not do any stuff. The following test shows you that the container does not keeps a reference nor dispose the inner ITest object.

DisposableCon tran;
using (WindsorContainer ioc = new WindsorContainer(new XmlInterpreter(“config1.xml”))) {
   tran = ioc.Resolve<
DisposableCon>(“TransientDisposableCon”);
}
Assert.IsFalse(tran.ITest.AProperty);

So it is your duty to be sure that the inner objects injected by the container will be disposed correctly.

Alk.

The importance of WindsorContainer.Release()

The WindsorContainer has a method call release that must be called to release the instance of transient object that gets created by the container itself. If you forget to call release, the container keeps a reference to all transient object created with resolve, that prevent the garbage collector from reclaiming the memory of that object. Suppose you have such a class.

public class DisposableTest : IDisposable, ITest {
   
public static Int32 NumOfDispose = 0;
 
   
private byte[] big = new byte[1000000];
 
#region IDisposable Members
 
   
public Boolean aProperty = false;
 
   
public void Dispose() {
      aProperty = 
true;
      NumOfDispose++;
   }
 
   #endregion
 
   #region ITest Members
 
   
public bool AProperty {
      
get { return aProperty; }
   }
 
   #endregion
}

This is a test class that implements IDisposable and ITest interface, the ItestInterface contains only the Aproperty property. The class logs the number of time that dispose gets called, and allocates a huge array just to waste memory. Now if you configure the lifecycle as transient and run this code, the program chrashes with a OutOfMemoryException

    1 using (WindsorContainer ioc = new WindsorContainer(new XmlInterpreter(“config1.xml”))) {
    2    for (Int32 I = 0; I < 10000; ++I) {
    3 
    4       ITest var = ioc.Resolve<ITest>();
    5       if (I % 100 == 0) {
    6          GC.Collect(2);
    7 
    8          Console.WriteLine(“Iteration: {0}, Memory {1} Dispose {2}”, 
    9                            I, GC.GetTotalMemory(false), DisposableTest.NumOfDispose); 
   10       }
   11       //ioc.Release(var);
   12    }
   13 }
   14 Console.WriteLine(“Number of Dispose Called {0}”, DisposableTest.NumOfDispose);

At line 6 I force a collect, but the memory cannot be reclaimed because the container keeps a reference to all the objects created with resolve. If you uncomment the ioc.Release() call, everything works fine and the program runs without problems. A different situation happens if you have this class, that simply declare a dependency from the ITest interface

public class DisposableCon {
 
   
public ITest ITest;
 
   
public DisposableCon(ITest iTest) {
      ITest = iTest;
   }
}

If you declare lifecycle as transient, you get a fresh new DisposableCon object and a new fresh DisposableTest each time you do a Resolve call. If you run the same test as above, even if you forget to call ioc.Release() the program runs fine, this because the container seems not to keep references of the transient object created to satisfy dependencies from other object. These two different behavior of WinsorContainer could be confusing for the user, but are reasonable because since I cannot obtain a reference to the instances created to satisfy a dependencies, the container should not keep any references to them. So keep attenction and remember not forget to call IoC.Release for transient instance of object created with the container.

Alk

VmWare update installer ( Vmdb error -2: Schema path not found )

This morning I turn on a virtual machine, and when I try to change configuration a strange error (Vmdb error -2: Schema path not found ) appears. After a little search I discover that my server version is version 1.0.3 and the console is 1.0.2. The error turns out to be caused by the installer of the upgrade. Instead of upgrading the old link it install side by site newer version of the client and create a new link. Since I thought that my old link was upgraded I did not notice the mismatch.

I think that a warning would be useful, something saying “You are trying to connect to a server newer than the console”

Alk.

Errata corrige

Thanks to my friend Janky for notice that I made a mistake in a previous post. In that post I speak about a “conversation” but actually I was describing a UnitOfWork, that was my fault. The exact definition of a conversation is given in “Hibernate In Action” where Gavin King states that.

“We call a unit of work that completes in several client/server request and response cycles a conversation“.

So a conversation is really a unit of work, but more complex than a standard one because it span several request, and naturally it use more than one NHibernate session.

Thanks again to janky for making me notice the error.

Alk.

IRepository and query objects

When you use a generic Interface for repository pattern there is always the problem of Query object. If you use nhibernate you can use Criteria API, but if you want to make your code not dependent by the ORM used, you often need to implement your Criteria Query. The most annoying problem with this approach is duplication of code, this because you usually create your query object and the concrete repository must translate from the Custom Query Object to the query object supported by the ORM framework.

A different approach is possible if you define such an Interface:

public interface IQueryBuilder {
   
IQueryBuilder Equal(String propertyName, object value);
   
IQueryBuilder LessThan(String propertyName, object value);
   
IQueryBuilder Greater(String propertyName, object value);
}

This is only an example, the real interface should expose all supported criterion. Now we create the concrete QueryBuilder, for example a Nhibernate repository.

public class QueryBuilder<T> : IQueryBuilder {
 
   
private ICriteria _criteria;
 
   
public QueryBuilder(ISession _session) {
      _criteria = _session.CreateCriteria(
typeof (T));
   }
 
   
internal IList<T> Execute() {
      
IList<T> result = _criteria.List<T>();
      
return result;
   }
 
   #region IQueryBuilder Members
 
   
public IQueryBuilder Equal(String propertyName, object value) {
      _criteria.Add(
Expression.Eq(propertyName, value));
      
return this;
   }
 
   
public IQueryBuilder LessThan(String propertyName, object value) {
      _criteria.Add(
Expression.Lt(propertyName, value));
      
return this;
   }
 
   
public IQueryBuilder Greater(String propertyName, object value) {
      _criteria.Add(
Expression.Gt(propertyName, value));
      
return this;
   }
 
   #endregion
}

As you can see the implementation is straightforward, you only delegate all the work to the real Criteria object, no intermediate custom Query Object is necessary, here is the function of the Generic repository:

public IList<T> GetByQuery(Proc<IQueryBuilder> configurator) {
   
QueryBuilder<T> qb = new QueryBuilder<T>(_session);
   configurator(qb);
   
return qb.Execute();
}

The trick is to use delegate. GetByQuery() method of the generic repository does not accept a query object, instead he need a function that is able to configure a query object through the IQueryBuilder interface, only three lines of code. The caller code is very concise too:

IList<Customer> AllCustomers = _customerRepo.GetByQuery(
   
delegate(IQueryBuilder qb) {
      qb.Equal(
“AddressInfo.City”, cityname);
   });

As you can see with anonymous delegate configuring a query is really a breeze. But the best thing of the whole stuff is the ability to test with mock object.

IRepository<Customer> mockrepo = mockery.CreateMock<IRepository<Customer>>();
IQueryBuilder querybuilder = mockery.CreateMock<IQueryBuilder>();

Expect.Call(querybuilder.Equal(“AddressInfo.City”, “ROME”))
   .Return(querybuilder);
Expect.Call(mockrepo.GetByQuery(null))
   .Constraints(
new PredicateConstraint<Proc<IQueryBuilder>>(
   
delegate  (Proc<IQueryBuilder> builder) {
      builder(querybuilder);
      
return true;
   }))
   .Return(Ret);

As you can see you can create the repository and the querybuilder with rhino mock, and you can first set the expectation on the IQueryBulder mock, then with PredicateConstraint you can set up your anonymous delegate used to call the delegate passed by the code under test. With this technique you can not only simulate the repository, but also you can check that the code under test configures the query correctly. The major problem with criteria API is that properties of the object are passed as string, with this technique you can check easily that all properties are spelled correctly.

Alk.

Â