Wednesday, December 13, 2006

Spring 2.0 Namespaces - Simply

I recently ended up doing some work with Spring 2.0 namespace support.
Generally we have 4 options for creating custom parsers (from most abstract to most defined):
  1. BeanDefinitionParser
  2. AbstractBeanDefinitionParser
  3. AbstractSingleBeanDefinitionParser
  4. AbstractSimpleBeanDefinitionParser
Out of all mentioned, 4th is the easiest to use. There isn't much you need to do for AbstractSimpleBeanDefinitionParser, just specify class name to configure and make sure that attributes in xml file match fields on the class (following attribute-something to attributeSomething conversion rule).
Even though option 4 is simplest to use in terms of general knowledge of Spring bean configuration internals, the convention is fairly restrictive. Most times I am itching to have xml attribute that does not match the property name on the bean that I am configuring.
The most common case is to have something like override="true" in xml vs. localPropertyOverride in bean. Other is to control two properties with a single attribute.

In such cases I found a it very useful to create a FactoryBean with the properties from XML and implement InitializingBean or some other callback mechanism to deal with all of the if/else, multi property setting in java vs. PropertyValue and xml Nodes.

This approach works good most of the time. There are obviously situations where it is best to still deal with configuration in namespace handlers manually. This would include anything that implements BeanPostProcessor/InstantiationAwareBeanPostProcessor for example. In that situation your factory would need to implement BeanPostProcessor also or its functionality will not get invoked.

If you decide to go the FactoryBean route to move configuration to java, consider any Spring dependencies that wrapped bean has. In case it does, make sure to test your namespace extension very carefully as it will be horribly simple to introduce very subtle bugs.