Customization of Spring beans

From time and time again, I’ve explained people (at work and at #spring@freenode.net) 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: -->
<beans>
  <bean id="abstractCustomizableBean" abstract="true" class="com.example.Foo">
    <description>Example of a simple parent-child customizable bean</description>
    <property name="bar" value="abbacd"/>
  </bean>

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

<!-- customerspecific.xml: -->
<beans>
  <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" />
  </bean>
</beans>

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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: