Thursday, December 17, 2009

3 Spring Stuff Worth Sharing

Firstly, Spring 3.0.0 is released not more than 2 days ago. Juergen (if you have the habit of reading source code, you shall know him) blogged about the features at Spring Framework 3.0 goes GA. I am particularly interested to explore more (possibly make changes to my existing project) in the area of @Configuration, SpEL, REST, OXM and validation.

I also upgraded my project this morning, with less than 10 lines of code changes to switch the plug from 2.5.6 to 3.0.0 - the compilation errors were some casting issues of generics type - yes, Spring 3 is now compile-time type safe. If you use Maven, you may want to read about the pom and repository configurations here.

Second-and-thirdly, below are some notes I wrote down in company's intranet. :)

Spring Resolves Dependencies and Initializes Accordingly, Not You

Before that, I thought implementing the Ordered interface could impact the order of which beans shall first be loaded. Then I realized, it doesn't work. Ordered is used.. as far as I can tell right now, two on top of my head: during invocation of Bean and BeanFactory post processing and the order of Advices - just not Bean initialization!

So how does it really work (for which bean to be loaded before any other)? One thing that I found (or maybe really just one): dependencies - bean references and @DependsOn/depends-on. When the BeanFactory preinstantiates the beans, it resolves its dependencies (via BeanDefinitionValueResolver) and eventually the beans who are referenced/dependent by others will be initialized first.

Do take note that, you rarely use @DependsOn unless you have static (*ugh!!*) references. For my case, HibernateSessionFactoryBean depends on SubEntityManager and those enums in it are accessed via the static (*ugh!!*) method SubEntityManager.getInstance() by the SubEntityUserType.

Spring Shutdown Hook and Unit Testing

A Spring ApplicationContext has a close() method, things like HibernateSessionFactoryBean will only be destroyed when the context is destroyed via the close() method - which is triggered by shutdown hook. See AbstractApplicationContext.registerShutdownHook(). So what is important here to know is, if you are running unit tests, a series of them, destroy can only happen when the shutdown hook is called.

Here's an example, I was running two test fixtures but the first one didn't shutdown until the whole test execution exited.
[12-16 16:26:45] INFO  GenericApplicationContext [Thread-4]: Closing ...startup date [Wed Dec 16 16:26:42 MYT 2009]; root of context hierarchy
[12-16 16:26:45] INFO  GenericApplicationContext [Thread-3]: Closing ...startup date [Wed Dec 16 16:26:34 MYT 2009]; root of context hierarchy
[12-16 16:26:45] INFO  HibernateSessionFactoryBean [Thread-4]: Closing Hibernate SessionFactory
[12-16 16:26:45] INFO  HibernateSessionFactoryBean [Thread-3]: Closing Hibernate SessionFactory