Rolling your own Spring documentation tool

It has been a few months since I came across Spring BeanDoc with its tantalizing screenshots of HTML documentation that could be generated from a Spring application XML configuration. Alas, BeanDoc could not process our project’s application context XML files because it did not support Spring 2.0 namespaces, specifically aop and tx which we use on our project. So after attending a friend’s memorial service 3 weeks ago, I decided to take action – write my own Spring documentation tool. Besides, I’ve encountered a few references to Spring “Tooling API”, and it was just too tempting not to take some spare time to explore it.

BeanDefinitionReader is your gateway into a Spring application context especially if you have configuration files and the one that was of interest to me was XmlBeanDefinitionReader. The reader’s purpose in life is to read a set of specified resources and load the bean definition registry (aka. application context).

Once that’s done, all the bean definitions are at your complete disposable including any other beans defined in resources imported through the XML file(s). All bean definition objects implement the BeanDefinition interface and depending on the implementation, they provide all the interesting information such as references to other beans, bean scope i.e. singleton or prototype, implementation class name. Thereafter, all you have to do is to resolve the dependencies and construct the dependency graphs for display.

public class DocApplicationContextGenerator {

	public DocApplicationContext generateBeanDoc(Resource[] resources) {

		// BeanDefinitionReader is configured through Spring
		getBeanDefinitionReader().loadBeanDefinitions(resources);
		BeanDefinitionRegistry defaultListableBeanFactory = getBeanDefinitionReader().getBeanFactory();

		<snipped/>
	}

}

Because the generator should work with combinations of readers and registries, the generator is itself configured using Spring and the current one is configured using an XMLBeanDefinitionReader and a DefaultListableBeanFactory. Here’s a snip of the Spring XML:

<bean id="DocApplicationContextGenerator" class="ca.intelliware.spring.doc.impl.DocApplicationContextGenerator">
	<description>Application context documentation generator</description>
	<property name="beanDefinitionReader" ref="BeanDefinitionReader"/>
	<property name="springBeanBuilder" ref="BeanBuilder" />
	<property name="beanDocReadEventListener" ref="ReaderEventListener" />
	<property name="txDependencyResolver" ref="TXDependencyResolver" />
</bean>

<bean id="BeanDefinitionReader" class="org.springframework.beans.factory.xml.XmlBeanDefinitionReader">
	<description>Application context bean definition reader</description>
	<constructor-arg>
		<bean class="org.springframework.beans.factory.support.DefaultListableBeanFactory"></bean>
	</constructor-arg>
	<property name="sourceExtractor">
		<bean class="ca.intelliware.spring.doc.impl.BeanSourceExtractorImpl">
		<description>Extracts meta informtation of beans from application context</description>
		</bean>
	</property>
	<property name="eventListener" ref="ReaderEventListener" />
</bean>

However, the BeanDefinition interface ignores the description tag from the XML configuration (see configuration above) since the description is irrelevant to the operation of the application context. Happily, XMLBeanDefinitionReader provides an XmlReaderContext during its loading process and the context can be configured with an implementation of a SourceExtractor (see configuration above).

The SourceExtractor is given an XML node (W3C) and its associated resource during the loading process so that the extractor has an opportunity to extract the appropriate information as required. The result of this extraction work is attached by the reader as an artifact on the bean definition.

The approach I took with the generator was to produce a simple application context bean. This bean should be easy to serialize into XML using XStream, relatively easy to read and transformed using simple XSL scripts. The client that consumes the bean would be responsible for producing the HTML documents and dependencies graphs according to project requirements.

So here is a screen shot of the HTML document when the generator is applied to its own Spring configuration. The document needs some styling tweaks but contain the cogent bits of information.

Most of the interesting work is done in resolving the transaction specifications of the Spring beans. More on that and on rendering the dependency graphs later in my next entry. (Note: since writing this, BeanDoc 0.8 is out last week and does support the new namespaces. Some comments about that later)

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply