Tuesday, June 17, 2008

Who hides in your Spring factory?

Using schema-based configuration in Spring framework is powerful yet leads to less transparent configuration. Here I introduce single class that allows you to unleash all details of your Spring context.

Schema based configuration

Spring framework has very interesting and powerful feature - ability to use custom namespaces within ordinary Spring configuration file.

Using that functionality, it's possible to create custom XML element (with providing necessary XSD scheme to Spring) that will be parsed and used for declaring specific beans that corresponds to appropriate custom tags from scheme.

That's feature is really cool, since, from one hand, it allows to create own DSL (domain specific language) that is plugged into usual Spring declaration. Using DSL instead of Spring declaration is pretty convenient since it allows to have clean, compact and, what is more important, domain specific markup instead of generic one.

In addition, by introducing support of such functionality, Spring encourages vendors of third-party tools and libraries to plug them into Spring as components with functionality exposed via elements in custom namespace provided by vendor.

In general, support of custom namespaces in Spring context brings higher level of abstraction and increases overall productivity of developers.

Caveat

Higher level of abstraction, as usual, adds more complexity and leaves many things under the hood. Until you use namespace you've implemented by own, you can now which beans will be created in Spring context as you use it (well, at least until during some reasonable period of time after developing it). However, what to do if you simply use tags provided by someone else? First, you got that library somehow and description of tag promises that if you use it you may throw away all old configuration for persistence, hibernate etc. etc. since at the moment of adding that custom tag into your context it scans your brain and does everything much better as you can even imagine... Sure thing, you think that it could be great and use it...

And until everything work fine - no one cares what is under that tag (it scans the brain, after all!). But if something goes wrong - well, if you have ordinary Spring config, you have a chance to take a look to configuration and find the problem' source. Not for custom tags - all details are hidden from outside world.

Seriously, using of custom namespaces in Spring config has such a drawback - in general, you don't know what actually happens when you use such a tags.

Solution

We here in SoftAMIS have got that problem some time ago trying to figure quite subtle problems with configuration. To avoid that in the future, we've created small utility that performs dump of internals for given Spring context (by examining registered bean definitions). Of course, it was not practical to invent some new format for such a dump, so old good Spring configuration is used - however, it unwraps all custom tags into their internal representation.

Similarly to approach from Spring reference:) If you have in your context declaration like that:

 

<util:map id="testMap"> <entry key="key" value="value"/> </util:map> <util:property-path path="testMap.values"/>

in corresponding dumped context you'll get:

<bean name="testMap" class="org.springframework.beans.factory.config.MapFactoryBean">
  <property name="sourceMap">
    <map> <entry key="key" value="value"/> </map>
  </property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean" name="testMap.values" p:propertyPath="values" p:targetBeanName="testMap"/>

How to use

To make dump of Spring context, I've wrote custom BeanFactoryPostProcessor. Ones is invoked by Spring automatically (if factory is created via application context) and simply inspects internal bean definitions registered in context and generates appropriate XML for them.

Therefore, everything you need to obtain dump of Spring factory - simply add the following declaration into context for wich you'd like to have such dump:

<bean class="org.softamis.tools4spring.dump.DumpBeanFactoryPostProcessor" p:generateSchemaBasedContext="true" p:outputLocation="z:\context.xml"/>

I's possible to specify location of file which dump should be written to and also specify whether dump should be created based on DTD or XSD. In later case, applicable attributes will be written using p: namespace

Of course, since that class works on context level, it's perfectly will dump Spring factory created from several configuration files.

License and download

To download source code for that class, please use this link. That class is licensed under Apache License, so it could be used both in open source and commercial applications.

I hope that this small utility will be helpful for you and will save your time in some tight situation.

1 comment:

Christian Schneider said...

Thanks for this great class. I am sure this will be extremly handy.

I have found two problems with the post and code.

The first is the description on how to include that class in the applicationcontext. The syntax p:generateSchemaBasedContext is not available in standard applicationcontexts. You should explain how to enable it.

The other problem ist with the Postprocessor itself. When I tried to use it on a context I got an Exception in processList. It tried to convert an ArrayList to a ManagedList and this did not work. When I looked into the method I realized that you do not use the features of the ManagedList. So I think you can simply omit the cast. What do you think?