Monthly Archives: June 2011

Notes for registering bean defs at runtime

When registering bean definitions at runtime via BeanDefinitionRegistryPostProcessor or the alike, always set the AbstractBeanDefinition.setResourceDescription(String). It will be shown you on the kilometre long exception reports when everything fails, thus helping you debug it. Even the following will tear less hair from your head:

private void registerFoo(String beanName, BeanDefinitionRegistry registry) {
  GenericBeanDefinition def = new GenericBeanDefinition();
  def.setResourceDescription(toString()); // or getClass().getName()
  registry.registerBeanDefinition(beanName, def);

The above will result in:

Exception in thread “main” org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [] for bean with name ‘foo’ defined in your-toString(); …

Instead of:

Exception in thread “main” org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [] for bean with name ‘foo’ defined in null; …

I first thought that it might be nicer to define beans in straight java, but I’ve now realized it gets more trickier (and non-obvious); save yourself and just do it the plain xml style!


Customization of Spring beans

From time and time again, I’ve explained people (at work and at how to do bean customization with the xml configuration.

The problem people seem to face (I know I did) is:

  • you have a “vanilla” or default configuration (what you ship to clients A, B, C)
  • you have a customer D, who would need/like things X, Y, Z be different

If you have coded spring-style beans, you will have a lot of properties (at least setters) you can modify in them — lets call this scenario A. If you’d need whole different implementation say, for example a strategy pattern you’d need to replace the definition in “vanilla” with a new one — scenario B.

Scenario B is more straightforward than scenario A. Basically what you’ll need to do is define the customized bean definition after the original (“vanilla”) definition. Remember that the two bean definitions (vanilla, customized) must have the same id attribute.

For web applications with web.xml this is achieved by including the vanilla.xml before customerspecific.xml.

Once you’ve done this, by turning up the logging for org.springframework for the refresh phase of ConfigurableApplicationContext you will see logging about this happening; of course you should try this out in a unit test to convince yourself that it actually works. (I’ll post a unit test example highlighting this solution once I figure a proper way of including snippets in this wordpress.)

Scenario A requires the same loading/inclusion procedure as Scenario B; you must load the vanilla before customized bean definition. However in this scenario you’ll often (or at least later on in development) run into a problem with the customized and vanilla definition sharing some properties (or even all properties, if you have two implementations with the same setters). You shouldn’t be forced to copy+paste those common properties as that will be an instant configuration nightmare.

Better is to have three bean definitions:

  • id=”abstractCustomizableBean”, abstract=”true”, with all the common properties
  • id=”actualCustomizableBean”, parent=”abstractCustomizableBean”, this is the vanilla bean definition
  • id=”actualCustomizableBean”, parent=”abstractCustomizableBean”, this is the customer specific bean definition
<!-- vanilla.xml: -->
  <bean id="abstractCustomizableBean" abstract="true" class="com.example.Foo">
    <description>Example of a simple parent-child customizable bean</description>
    <property name="bar" value="abbacd"/>

  <!-- concrete definition: note that this inherits all props from parent -->
  <bean id="customizableBean" parent="abstractCustomizableBean"/>

<!-- customerspecific.xml: -->
  <bean id="customizableBean" parent="abstractCustomizableBean">
    <!-- customer needs this message to have a meaning -->
    <property name="bar" value="ACMEBar" />
    <!-- they also required that the interval must be precisely 5 seconds -->
    <property name="interval" value="5" />

In best case scenario, your “abstractCustomizableBean” definition will contain class and all other required attributes and most, if not all, properties for the vanilla.xml’s “actualCustomizableBean”. This will render vanilla.xml “actualCustomizableBean” to define just the parent.

Then in the last definition you’ll only specify the customer specific properties and their respective values.

For added “customizability” you might want to keep vanilla’s “actualCustomizableBean” definition right under the “abstractCustomizableBean”, so that all your coders will quickly find the “defaults” as they grep through for “actualCustomizableBean.”

(As said above, I’m in the process of trying to figure how to add properly formatted code/xml in these posts, will update it later on.)

EDIT: Added at least some XML, as promised.