Running BeanDoc

BeanDoc attempts to be a very flexible tool without incurring a steep learning curve. In the simplest configurations you only need to specify your inputs (one or more Spring context XML files) and an output location. If you wish to take advantage of the graphing output too (highly recomended, see overview) you'll additionally need to specify the location of your GraphViz "dot" executable once it's installed.

Running from the command line

The bin directory contains a simple shell script to enable you to test the BeanDoc tool. Check that you have made the shell script executable before trying to run it. The script requires one argument - the location of your beandoc.properties file..

> ./bin/run.sh /path/to/beandoc.properties

Using the ant task

An ant task for beandoc is included in the beandoc JAR file. The following snippet shows how to define and use the task..

<project name="myproj">

    <property name="output.dir" value="target/beandoc"/>
    
    <!-- should point to all the libs shipped with beandoc
         in its /lib directory -->
    <path id="beandoc-classpath">
        <fileset dir="${lib.dir}">
            <include name="**/*.jar"/>
        </fileset>
        <dirset dir="${basedir}"/>
    </path>
  
    <!-- define the task -->
    <taskdef 
        name="beandoc"
        classname="org.springframework.beandoc.client.AntTask"
        classpathref="beandoc-classpath"/>
        
    <target name="beandoc">
        <mkdir dir="${output.dir}"/>
        <beandoc  
            outputDir="${output.dir}"
            beandocProps="${basedir}/beandoc.properties">
            <fileset dir="${basedir}/src/config">
                <include name="*.xml"/>
            </fileset>
        </beandoc>
    </target>
</project>

Configuration

However you choose to run BeanDoc, specifying configuration is in most cases identical. Let's look at the simplest case; specifying inputs, outputs and graphing binary location only.

input.files=/projects/my-spring-project/*.xml
output.dir=/projects/my-spring-project/beandoc/
compiler.dotExe=C:/Program Files/ATT/GraphViz/bin/dot.exe

The above values are saved in a properties file, the location and name of which can be anything you like, but I'll assume it's been saved as /projects/my-spring-project/beandoc.properties since that's as good as anywhere. Inputs and output directory can optionally be specified on the command line (for CLI), as Ant task attributes (for Ant) or as System properties to the JVM (qualified with "springbeandoc."). More detail on this is in the relevant sections below. All other configurable options are specified through the properties file, so for now, we'll stick to specifying everything in here.

input.files are expected to point to one or more Spring XML files. You can use any string that represents a Spring Resource or array. Some other possibilities are below;

input.files=/projects/my-spring-project/file1.xml,/projects/my-spring-project/file2.xml
input.files=classpath:/com/foo/bar/context.xml
input.files=C:/projects/my-spring-project/*.xml

BeanDoc will alway aggregate all files supplied into a single logical ApplicationContext or BeanFactory and will always assume that you are specifying files on a file system by default (rather than defaulting to classpath resources). If your resources are on the classpath, use the classpath: qualifier on the resource names.

Further configuration

When using either the BeanDocClient class or the AntTask, you can also specify any beandoc properties as System properties. If you do, they must be qualified with a prefix of "springbeandoc." to prevent potential namespace collisions. For example;

> ant -Dspringbeandoc.input.files=/path/to/input.xml

System properties are lowest in the hierarchy of places to beandoc properties and will be ignored if the values are specified in a beandoc.properties file. In turn, locations specified in beandoc.properties files will be overridden by any listed as arguments to the BeanDocClient class' main method, or those defined as attributes to the AntTask class.

HTML and JavaDoc

Principal properties you may wish to tweak to affect HTML output are the page title, page footer and the location of a CSS URI that enables you to skin the output to suit your corporate or project needs. All of these are specified in the beandoc.properties file shown below.

# page title used in <title/> tags and page headings
html.title=My Application Context

# page footer
html.footer=Copyright (C) ACME Corp. 2007

# override the default CSS file to skin the output to your liking
html.cssUrl=http://our.intranet/projects/beandoc.css

# set this to false if you DON'T wish to see graphs in your HTML
# docs (or if you aren't generating graphs).  Defaults to true
html.includeGraphs=false

Default values for all of the above will be used if you don't specify them, and additionally, a default CSS file will be copied to the output location that you specify and this will be used in all HTML output. For further information on configuring the HTML output, see the javadoc for HtmlDecorator

Most of the beans defined in your context files will have a class attribute. In many instances this will be linked to the relevant JavaDoc page for that class. BeanDoc has many well known JavaDoc locations built-in such as Java runtime classes, SpringFramework classes and man of the Jakarta Commons projects. You may however wish to add your own locations for your custom code, or override existing ones if, for example, you have local copies of the JavaDoc somewhere.

Specify the root of the apidoc for your class prefixes in beandoc.properties like so;

javadoc.locations[com.foo.bar]=http://your.local.server/apidoc/
javadoc.locations[org.something.else]=http://another.server/javadoc/

You can add or override as many different locations as you like. More specific package names will be evaluated before less specific names - so if you defined the following two locations..

javadoc.locations[com.foo.bar]=http://www.foo.bar/apidoc/
javadoc.locations[com.foo.bar.web]=http://your.local.server/apidoc/

.. then classes in the com.foo.bar.web package would be linked to your.local.server while all other classes in the com.foo.bar hierarchy would be linked to www.foo.bar instead. If you wish to suppress javadoc links for a package prefix that might otherwise have links, specify the empty string as the location;

javadoc.locations[com.foo.bar]=http://www.foo.bar/apidoc/
javadoc.locations[com.foo.bar.web]=

Localisation

The majority of the BeanDoc output is entirely dependent upon the names and descriptions found within your context definition files. There are a few static labels however and these will be shown either in the language of the system default locale, or the base language (English) if no translation file exists for the default locale. You can override this behaviour in beandoc.properties by specifying the language or locale you want to see in the output.

# example of overriding the system locale to get Spanish output
i18n.locale=es_ES

Of course, if no translation exists for the specified override, you will get system default values if available or English if not. See our translations page for more information.

Graphs

Graphing output is quite customisable through the beandoc properties file and some of the more common options that you may wish to explore are listed below. Information on BeanDoc's default graphing output and the meaning of various styles, can be found in appendix A

Color

BeanDoc specifies a default set of colours for beans with certain naming patterns. These can be added to or overridden as required. You can specify colours for patterns based on the bean name (id) or the bean's fully qualified class name. The format for doing so is to set a property like;

graphs.colourBeans[NameOrClassPattern]=colour

where NameOrClassPattern is a standard Regex pattern to match against. Some examples are shown below:

graphs.colourBeans[com\.foo\.bar.*]=#a090a0
graphs.colourBeans[^Service.*]=#f0f080
graphs.colourBeans[.*Proxy$]=blue

In the examples shown, beans in the package com.foo.bar will all be coloured #a090a0, any bean whose name or id attribute begins with the String "Service" will be coloured #f0f080 and any bean whose name ends in the String "Proxy" will be coloured blue.

Note that you can also override the default colour for beans with no other colour specified from the dark-gray by setting the property graphs.defaultFillColour=#aaaaaa as appropriate.

Output Type

By default, BeanDoc produces graph images in PNG (Portable Network Graphics) format. This is a highly efficient, open standard image format and is supported by the vast majority of current web browsers. You can however override this format and have graphs produced in other formats if desired. The relevant property is;

graphs.outputType=[OutputType]

Some common output types that you may like to specify are;

  • png
  • gif
  • jpg
  • svg
Label Styles

BeanDoc attempts to use Helvetica with a point size of 10 for all graph and bean labels, but again this can be overridden in your beandoc.properties. Note that on Win32 platforms, this should just work for any font you have installed, but for Unix/Linux it depends on your font server setup and font directory locations. If you have trouble on these platforms with graphs not displaying the font you requested, try setting an environment variable (process will depend on your particular shell) named DOTFONTPATH and specify your font directories as a path separated (:) list. Below are examples of setting the style attributes in beandoc.properties;

graphs.fontSize=20
graphs.fontName=Arial
graphs.labelLocation=b

In the above list, the labelLocation additionally specifies that graph titles should be at the bottom (b) of the graph. By default, they are at the top (t).

Graph size & ratio

GraphViz attempts to create graphs as space efficiently as possible, however you may sometimes wish to constrain the final size of a graph - in particular for printing purposes. You can modify the aspect ratio of final output, or specify hard size limits (in inches) of the final output. The example below will attempt to force the graph to a size that can be printed on a single A4 sheet.

graphs.graphXSize=11.5
graphs.graphYSize=8.5

Aspect ratio can be affected by specifying the value of graphs.ratio as a floating point number.

Because of the extreme effect that the above properties can have on output, there are no real best practices or sensible defaults - you will just have to experiment and choose settings that work for your particular project.

Selectively ignoring beans on graphs

Some beans may not benefit from being graphed, even though they are still documented in the HTML. Often, message source or post- processing type beans don't benefit from being graphed and simply clutter the output. You can choose to ignore any number of beans based on either their id's/names or class names by specifying one or more Regular Expressions in beandoc.properties

graphs.ignoreBeans[0]=org\.springframework\..*Property.*Configurer$

The above line will cause all Spring property configurer type beans to be left off the graphs.

Selectively ranking beans on graphs

Some graphs will contain beans that are unreferenced in any way and without further information, GraphViz will simply dump these all at the top of the graph which may make the graph too wide or show an illogical separation of similar beans. You can force beans of a certain type or with a similar naming pattern to all occupy the same rank. Use this option with care - it may be a better option to leave unreferenced beans off the graphs altogether.

graphs.rankBeans[0]=some.*RegexPat*ern
graphs.rankBeans[1]=com\.foo\.bar.*

In the above code, all beans whose names match the pattern "some.*RegexPat*ern" will be forced onto the same rank - REGARDLESS of any references held between them. Likewise, any beans in the package "com.foo.bar" will be forced into sharing their own rank.

In the example above, if a bean matched both patterns, then all beans matching either pattern will all share the same rank in the graph. This option should be used with care, GraphViz works best when it has more freedom to optimise layouts.

Selectively merging proxy beans

This option is most useful if your context files contain proxies and targets where the target bean is not modelled as an anonymous inner bean. There are several reasons for wanting to do this such as making the un-proxied target available to unit tests. However, when graphing the context, you only want to show the proxy with dependencies of the inner bean looking like dependencies of the proxy instead. By default, the graphs will show your proxy and its target as two separate beans.

In beandoc.properties, you specify one or more RegEx expressions that match either the class name or the id of the proxy bean and set the value of the name of the property that has a reference to its target. Typically this is "target". Here's an example of a context configuration highlighting the problem..

<beans>
  <bean id="myProxy" class="com.foo.bar.SomeProxy">
    <property name="target"><ref local="myProxyTarget"/></property>
  </bean>

  <bean id="myProxyTarget"/>
</beans>

Ensure when picking a regular expression that matches your proxy beans that you don't inadvertently match more beans than you intended - remeber, the match will occur against either id/name or class attributes. The two beans above can be merged with the following line in beandoc.properties..

processor.mergeProxies[^myProxy$]=target

The RegEx is very restrictive, being guaranteed to exactly match a single bean with a name or id "myProxy". If you wanted all of your SomeProxy classes to be matched, you could perhaps write instead..

processor.mergeProxies[com\.foo.*SomeProxy$]=target

Advanced configuration

As you may already have worked out, the beandoc.properties file is used to post-process a Spring bean factory that the BeanDoc tool uses to configure itself. In fact, the bean factory is post-processed twice using the same properties file - once to pull values for input.files and output.dir, and once to push all the other values. This is what makes it possible to specify any property on any named bean in the context file using standard Spring methods. You should take a look at the beandoc.xml file in the source code (org.springframework.beandoc.client.beandoc.xml) in conjunction with the BeanDoc API in order to see exactly what properties you have available for configuration.

Replacing XSL templates

HTML and standard graphing output is fairly configurable as we've so far seen, but if you really need some weird and wonderful output or layout, or a different markup language altogether, then one option is to define your own XSL templates for beandoc.

Once you have your templates, simply set the relevant properties in your beandoc.properties file. You may not need to override all of these and can just ignore the output you don't need.

# this one generates the frameset document
htmlIndexTransformer.templateName=classpath:my/frameset/stylesheet.xsl
# this one generates the navigator (All Beans)
htmlNavigationTransformer.templateName=/filesystem/path/to/my/navigator/stylesheet.xsl
# this one generates the index page with the consolidated graph
htmlMainTransformer.templateName=classpath:my/main/stylesheet.xsl
# this one generates the individual context file documents
htmlDetailTransformer.templateName=classpath:my/detail/stylesheet.xsl

Replacing the XSL templates means you still have to work with the decorated DOM's that BeanDoc produces based on its configured Map of Decorator implementations. In order to see a plain text XML rendition of this DOM you can use the supplied EchoTransformer and add it to the list of Transformers in BeanDoc's own context definition file. See the API documentation and the next section on replacing context files for more information. If you need additional attributes or amended elements, you will need to define your own Decorator and add it to the decorator map.