Spring Simplified with XBean - No Fluff Just Stuff

Spring Simplified with XBean

Posted by: Craig Walls on October 13, 2005

A complaint that I frequently hear about Spring is that the Spring XML configuration files can be somewhat verbose and unwieldy. It's true...while working with Spring XML files, you can easily get lost in a endless sea of <bean> and <property> tags.

As I see it, there are two problems with Spring's configuration XML:

  1. It's too verbose
  2. It's not expressive enough

The verbosity issue is self-explanatory. But Spring configuration files are also not very expressive in that the XML tags are non-descript <bean> and <property> tags. These tags, by themselves, do not tell you anything about the context of the objects that they define. To illustrate, consider the following standard Spring configuration XML:

<beans>
  <bean id="quest"
      class="com.springinaction.chapter01.knight.HolyGrailQuest"/>

  <bean id="knight"
      class="com.springinaction.chapter01.knight.KnightOfTheRoundTable">
    <property name="moniker">
      <value>Bedivere</value>
    </property>
    <property name="quest">
      <ref bean="quest"/>
    </property>
  </bean>
</beans>

Spring has no problem parsing this file. Everything Spring needs to know to configure a knight and a quest can be found among the XML. But for the human who reads and writes this XML, you'll need to do a bit of deciphering. The <bean> tag only tells you that you are dealing with a bean. If you want to know what kind of bean you're dealing with, you must look at the class attribute. To see how it's configured, you have to examine the <property> tag's name attribute and <value> and <ref> sub-elements.

Spring is still quite useful despite these problems. But wouldn't it be nice if something could be done to make the Spring configuration files simpler and more expressive?

Spring itself offers a couple of ways to shorten your configuration XML. Auto-wiring cuts down on the number of <property> tags in your configuration by allowing Spring to guess which beans should be wired into properties using hints based on the property's name or type. And, as of Spring 1.2, short-hand XML makes it possible to roll property values and references from XML sub-elements into attributes. For example, the XML above can be shortened a bit by applying both auto-wiring and short-hand XML:

<beans>
  <bean id="quest"
      class="com.springinaction.chapter01.knight.HolyGrailQuest"/>

  <bean id="knight"
      class="com.springinaction.chapter01.knight.KnightOfTheRoundTable"
      autowire="byName">
    <property name="moniker" value="Bedivere" />
  </bean>
</beans>

The XML is a bit shorter, but it's still not very expressive. If anything, auto-wiring has eliminated some of the clarity of what is being wired. There's nothing in this XML to explicitly tell us that the quest property of the "knight" bean is being wired.

Enter XBean

XBean is an extension of Spring that makes it possible to customize Spring's configuration XML to hit the sweet-spot where it is both terse and expressive. Simply put, XBean automagically maps XML elements and attributes to JavaBean classes and properties using reflection and simple conventions. When using XBean, you are able to extend Spring's XML configuration files with custom XML tags and attributes that describe the beans that you are configuring.

The first step in using XBean is to download it. XBean is in the process of evolving from the GBean project, so it's tricky to find the JAR file. I found it sitting in Codehaus's Maven repository at xbean-spring-1.0-SNAPSHOT.jar.

In this article, I'm going to show you how to apply XBean to the Knight example from chapter 1 of Spring in Action. For these examples, the minimum set of JAR files you'll need are:

  • spring.jar
  • commons-logging.jar
  • jaxrpc.jar
  • xbean-spring-1.0-SNAPSHOT.jar

With the exception of the XBean JAR, I found all of these JAR files in the distribution of Spring 1.2.5.

It should be noted that the use of XBean is still cutting edge stuff. The fact that I had to dig around in Codehaus' Maven repository to find a JAR should indicate that although it seems to work fine in these examples, mileage may vary from project to project. Use with caution.

UPDATE: James Strachan informs me that the official XBean website is up. No need to dig around in Codehaus' Maven repository! However, it is still a pre-1.0 snapshot release, so continue to exercise caution in using it.

Setting the stage

To get started, consider the KnightOfTheRoundTable class that we'll be working with:

package com.springinaction.chapter01.knight;


public class KnightOfTheRoundTable implements Knight {
  private String moniker;
  private Quest quest;
  
  public KnightOfTheRoundTable() {}
  
  public Object embarkOnQuest() throws QuestException {
    return quest.embark();
  }
  
  public void setQuest(Quest quest) {
    this.quest = quest;
  }

  public String getQuest() {
    return quest;
  }
  
  public void setMoniker(String moniker) {
    this.moniker = moniker;
  }
  
  public String getMoniker() {
    return moniker;
  }
}

If you're comparing this class with the same class from Spring in Action, you'll notice that I tweaked things a bit. First, I changed the class to be able to set both properties via a setter method (instead of by constructor). That's because when you're using XBean, setter-injection is the way to go.

But even more noticeable than that, the name property has been renamed to moniker. Aside from looking for a valid excuse to use the word "moniker", there is a more practical reason why I made this change. But, I'll save that explanation until a bit later.

Now take a look at the HolyGrailQuest class:

package com.springinaction.chapter01.knight;

public class HolyGrailQuest implements Quest {
  public HolyGrailQuest() {}
  
  public Object embark() throws GrailNotFoundException {
    // do whatever it means to embark on a quest
    System.out.println("Embarking on HolyGrailQuest");
    return new HolyGrail();
  }
}

There's nothing too remarkable about this class. In fact, it's virtually identical to the same class in Spring in Action. I have added a System.out.println() to prove that the embark() method is getting called, but other than that it's the same class.

Customizing Spring XML

To configure these two classes as beans in Spring, you could use either of the XML configurations listed earlier in this article. But using XBean, things get simplified a little:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans xmlns:k="java://com.springinaction.chapter01.knight">
  <k:HolyGrailQuest id="quest" />

  <k:KnightOfTheRoundTable id="knight" moniker="Bedivere">
    <property name="quest" ref="quest" />
  </k:KnightOfTheRoundTable>
</beans>

Notice that instead of using <bean> tags, I'm able to use <k:HolyGrailQuest> and <KnightOfTheRoundTable> tags. These tags map directly to the HolyGrailQuest and KnightOfTheRoundTable classes. These classes are found by way of the XML namespace which is associated with the Java package that the bean classes are in.

Also notice that instead of setting the "moniker" property via a <property> tag, we're setting it as an XML attribute of the <KnightOfTheRoundTable> tag. This is why I had to change the property name to "moniker" instead of "name". In Spring, the "name" attribute already has a meaning (similar to that of the "id" attribute) and XBean won't let me set a property called "name".

At this point, the XML elements have a bit more meaning. It's clear from the tags themselves that we're configuring a HolyGrailQuest and a KnightOfTheRoundTable. To be able to use this XML, you'll need to use an XBean-specific application context. XBean comes with four application contexts:

  • org.xbean.spring.context.ClassPathXmlApplicationContext
  • org.xbean.spring.context.FileSystemXmlApplicationContext
  • org.xbean.spring.context.ResourceXmlApplicationContext
  • org.xbean.spring.context.XmlWebApplicationContext

Each of these application contexts mimic the corresponding application context of the same name in the Spring JAR (that is, except for ResourceXmlApplicationContext which has no twin in Spring). You use an XBean application context just as you would its corresponding Spring application context. For example:

  ApplicationContext ctx = new
      FileSystemXmlApplicationContext("knight.xml");

  KnightOfTheRoundTable knight = 
      (KnightOfTheRoundTable) ctx.getBean("knight");

  System.out.println("Knight's name:  " + knight.getMoniker());
  knight.embarkOnQuest();

The XBean version of the Spring configuration above is more expressive than the plain-vanilla Spring configuration, but there's even more that can be done. First, KnightOfTheRoundTable and HolyGrailQuest are lengthy names for XML tags. Let's see how to shorten them.

In the example above, the XML namespace was a "java://" URI and XBean assumed some simple conventions for the XML tags and attributes. But if the namespace is an "http://" URI, it can be used to lookup a properties file that guides XBean to alias class names and property names into custom XML tags and attributes.

For example, if the XML namespace is changed to "http://springinaction.com/schemas/knight", XBean will look in the classpath for a property file named "knight" in META-INF/services/org/xbean/spring/http/springinaction.com/schemas. I used the following "knight" property file to change the <KnightOfTheRoundTable> and <HolyGrailQuest> tags to <knight> and <quest> tags:

# The default package
package = com.springinaction.chapter01.knight
knight = com.springinaction.chapter01.knight.KnightOfTheRoundTable
quest = com.springinaction.chapter01.knight.HolyGrailQuest

After saving the "knight" properties file in META-INF/services/org/xbean/spring/http/springinaction.com/schemas, I am able to change my Spring configuration XML to look like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans xmlns:k="http://springinaction.com/schemas/knight">
  <k:quest id="quest" />

  <k:knight id="knight" moniker="Bedivere">
    <property name="quest" ref="quest" />
  </k:knight>
</beans>

That's a little bit cleaner. The only argument against aliasing class and property names is that the Spring XML file no longer is clear about exactly which classes and properties are being manipulated. In order to get a clear picture of the real classes and properties involved, you must read the configuration file alongside the properties file. If that's a problem for you, then I recommend that you not create alias tags.

We're making a lot of progress, but there's still that Spring-esque <property> tag used to wire the "quest" bean into the "quest" property of the "knight" bean. How can we make that line more expressive?

It just so happens that you can use XML sub-elements to wire in objects just as you might use XML attributes to configure String or other native properties. So, instead of <property name="quest"> we can use a <quest> tag:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans xmlns:k="http://springinaction.com/schemas/knight">
  <k:knight id="knight" moniker="Bedivere">
    <quest><k:quest/></quest>
  </k:knight>
</beans>

Now the XML is very terse and a lot more expressive. There's one more thing we can do, though. Let's move the XML namespace declaration to the <knight> tag, so that we can eliminate the XML namespace prefix:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <knight id="knight" moniker="Bedivere"
      xmlns="http://springinaction.com/schemas/knight">
    <quest><quest/></quest>
  </knight>
</beans>

This Spring configuration XML is much better. Using XBeans, we've dramatically reduced the verbosity and made each tag name mean something.

The only questionable aspect of this last version of the XML is that the <quest> tag has a double-meaning. The outer <quest> tag is setting the "property" of the "knight" bean, while the inner <quest> is instantiating a HolyGrailQuestion object. I personally don't consider this a huge issue, but if it bugs you, then there are a couple of options.

The first and most obvious option is to keep the XML namespace at the root level and continue using the namespace prefixes. That's not too bad, but I find that the prefixes hinder the readability of the XML. Another option is to edit the "knight" properties file and choose a different alias for the HolyGrailQuest class other than "quest". That's easy enough to do, but let me suggest a third option.

Just as we were able to apply aliases to our bean classes using the "knight" properties file, we can also apply aliases to the bean properties. For example, to alias the knight's quest property as "myQuest", simply add the following line to the "knight" properties file:

knight.myQuest=quest

Here we're effectively creating a new XML tag called <myQuest> that will be used to inject values into the knight's quest property. Thus, the XML can be changed (one more time) to the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <knight id="knight" moniker="Bedivere"
      xmlns="http://springinaction.com/schemas/knight">
    <myQuest><quest/></myQuest>
  </knight>
</beans>

Note that although we're aliasing the quest property here to create a new XML tag, the same technique can also be used to alias an XML attribute.

Where we've come from

In weight-loss advertisements, it's customary to see a before and after picture so that you can appreciate how much progress has been made. The transformation we've taken Spring's XML through is not unlike some form of weight-loss--we've taken a bulky and boring XML document and made it lean and mean. So, I thought it'd be good to see a before and after picture of the knight configuration file side-by-side:

Before (Standard Spring)After (Using XBean)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="quest" class=
      "com.springinaction.chapter01.knight.HolyGrailQuest"/>

  <bean id="knight" class=
      "com.springinaction.chapter01.knight.KnightOfTheRoundTable">
    <property name="moniker">
      <value>Bedivere</value>
    </property>
    <property name="quest">
      <ref bean="quest"/>
    </property>
  </bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <knight id="knight" moniker="Bedivere"
      xmlns="http://springinaction.com/schemas/knight">
    <myQuest><quest/></myQuest>
  </knight>
</beans>

(Sorry about the small font size...it was necessary in order to squeeze the examples in side by side.)

Be aware that these two XML files are effectively identical in purpose. They both instantiate HolyGrailQuest and KnightOfTheRoundTable objects and then wire the "quest" bean into the knight's quest property. But the difference is obvious: The XBean version is much cleaner, shorter, and easier to read. The knight example was brief to begin with, but using XBean, it became much simpler and clearer. As an exercise to the reader, imagine how XBean could be used to simplify the configuration of a much larger Spring application.

As an example of how XBean is being used, consider ServiceMix. The current release of ServiceMix (v1.0.1) comes with a modified version of Spring to simplify configuration of the ESB from a complex <bean>/<property> approach to a more terse and expressive <container>/<components>/<component> approach. Unfortunately, however, because ServiceMix is using a modified (i.e., "unofficial") release of Spring, you are unable to use a newer release of Spring with ServiceMix. This will change in a future release of ServiceMix, however, as they replace their custom Spring code with XBean for configuration. Once ServiceMix uses XBean, you'll be free to choose any official Spring release for your project.

For your convenience, I've placed the source code from this article, along with all necessary JAR files for download here. The included Ant build file will compile and run the example using the final version of the Spring/XBean XML file. To swap out different versions, edit the com.springinaction.chapter01.knight.KnightApp class to load its context from one of the other XML files.

Craig Walls

About Craig Walls

Craig Walls is a Principal Engineer, Java Champion, Alexa Champion, and the author of Spring AI in Action, Spring in Action, and Build Talking Apps. He's a zealous promoter of the Spring Framework, speaking frequently at local user groups and conferences and writing about Spring. When he's not slinging code, Craig is planning his next trip to Disney World or Disneyland and spending as much time as he can with his wife, two daughters, 1 bird and 2 dogs.

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »