Using FactoryBeans to create the ‘uncreatable’

In response to a post by Carlos Sanchez and one by Marc Logemann I’d like to elaborate a bit on the concept of Spring FactoryBeans and how Spring features a lot of FactoryBeans that make life a little easier.

The Spring FactoryBean is a special kind of bean that adds a level of indirection by means of which you can incorporate any type of object in a Spring ApplicationContext.

Examples of setter-injection and constructor-injection

Let’s first shortly review the ‘normal’ way Spring creates your objects. Beans are normally created by Spring using either a no-args constructor (after which property values are set to the bean instance) or by using XML-specified constructor arguments. The first option is called ’setter-injection’ while the latter is called ‘constructor-injection’. Let’s review both ways of wiring beans in Spring. Consider the following test bean and the two XML fragments below.

public class TestBean {
  private String name;
  private int age;
 
  public TestBean() {
  }
 
  public TestBean(String name) {
    this.name = name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  public void setAge(int age) {
    this.age = age;
  }
}
# normalBeans1.xml
<bean id="setter" class="example.TestBean">
  <property name="name" value="Alef [setter]"/>
</bean>
 
<bean id="constructor" class="example.TestBean">
  <constructor -arg value="Alef [constructor]"/>
</bean>

As you can see, both setter-injection and constructor-injection are pretty easy to use.

Mixing setter-injection and constructor-injection

You can also mix setter-injection and constructor-injection if you like. So if (considering the TestBean shown above) we’d like to use constructor-injection and also set the age property, we’d have to do the following:

<bean id="mixed" class="example.TestBean">
  <constructor -arg value="Alef [mixed]"/>
  <property name="age" value="27"/>
</bean>

The configuration above will cause Spring to first instantiate the TestBean using the ‘Alef’ constructor argument. After the bean has been created, Spring will also apply the age attribute (by calling the setAge() method).

So now we have all the things we need to instantiate all different kinds of objects and configure them. We can construct objects with both normal JavaBeans constructors (default, no-args constructors that is), configure properties by their appropriate setters and configure objects using constructors with arguments while also being able to set additional properties on those objects.

Objects created by factories and other types of objects
But wait! But what if an object does not have a public constructor of some sort that we can use to create the object. Using the approaches we mentioned above, we’re still not able to create such objects. And also, if an object needs additional configuration that we cannot perform using either constructors or JavaBean properties (setters), we’re not able to create those objects as well.

This is where the FactoryBean comes in!

A Spring FactoryBean is (and I’m quoting the FactoryBean’s JavaDoc here) an ‘Interface to be implemented by objects used within a BeanFactory that are themselves factories. If a bean implements this interface, it is used as a factory, not directly as a bean.’

The FactoryBean is a pretty simple interface with just three methods:

  • Class getObjectType() - determines the type of object the factory returns
  • boolean isSingleton() - does this factory always return the same object or does it create new objects each time getObject() is called?
  • Object getObject() - is supposed to create an object and return it

Let’s review a simple implementation of the FactoryBean:

public class SimpleFactoryBean implements FactoryBean {
 
  public Class getObjectType() {
    return TestBean.class;
  }
 
  public boolean isSingleton() {
    return false;
  }
 
  public Object getObject() {
    return new TestBean("Alef [factory]");
  }
}

… and a small piece of XML:

# factoryBean2.xml
<bean id="simpleFactoryBean" 
  class="example.SimpleFactoryBean"/>

To illustrate how Spring FactoryBeans work in practice, we’ll use the programmatic API to retrieve beans from the ApplicationContext. Note that this is usually not the way to go about retrieve beans from a context but for now it serves as a good example. First, we have to load our application context using the ClassPathXmlApplicationContext class for instance:

ApplicationContext ctx = new ClassPathXmlApplicationContext(
  new String[] { 
    "normalBeans1.xml", 
    "normalBeans2.xml",
    "factoryBeans1.xml" });

Using the getBean() method (it takes a String representing the bean identifier) we can retrieve beans from the ApplicationContext. So the following would all return a TestBean as expected.

TestBean tb = (TestBean)ctx.getBean("setter"); 
assertEquals("Alef [setter]", tb.getName());
tb = (TestBean)ctx.getBean("constructor");
assertEquals("Alef [constructor]", tb.getName());
tb = (TestBean)ctx.getBean("mixed");
assertEquals("Alef [mixed]", tb.getName());

But - and this is where the FactoryBean comes in - the following also returns a TestBean. Instead of returning the SimpleFactoryBean we’ve defined in the application context, Spring retrieve the factory bean and called getObject(). The result is returned to the caller.

TestBean tb = (TestBean)ctx.get("simpleFactoryBean");
assertEquals("Alef [factory]", tb.getName());

More useful usage scenarios

Of course using the SimpleFactoryBean to return instances of the TestBean class is a bit useless since we could just as easily have wired up the test bean class itself (like we did in the earlier examples). There are however a couple of interesting scenarios in which the FactoryBean class turns out to be the only way you can wire up objects in a Spring context without too much hassle. Let’s review some of those scenarios.

Objects obtained from ’strange’ locations

Consider objects obtained from a JNDI context like DataSources. We can just ‘new’ a DataSource because we want to have the DataSource configured in JNDI. So it has to be explicitly retrieved from the JNDI tree by creating a new InitialContext and using its lookup() method. Not exactly JavaBean-friendly. Because we still want to wire DataSources in our Spring context for example we need some level of indirection. The FactoryBean provides a solution. Consider the following FactoryBean (which is a simplified version of the org.springframework.jndi.JndiObjectFactoryBean):

public class JndiObjectFactoryBean implements FactoryBean {
 
  private String jndiName;
  
  public void setJndiName(String jndiName) {
    this.jndiName = jndiName;
  }
 
  public Object getObject() {
    // let's not worry about exceptions
    // and closing the context for now
    Context ctx = new InitialContext();
    return ctx.lookup(jndiName);
  }
}

Using the following piece of XML, we’re able to wire up DataSource and use them as references in other beans without having to resort to lookup code. In other words, we’re able to dependency inject the DataSource! Note that in this example, we’re also configuring the FactoryBean so we don’t have to hardcode the JNDI location. Remember that we’re not configuring the DataSource here, we’re configuring the FactoryBean.

# jndiFactory.xml
<bean class="example.MyDao">
  <property name="dataSource ref="myDataSource"/>
</bean>
 
<bean id="myDataSource" class="example.JndiObjectFactoryBean">
  <property name="jndiName" 
    value="java:comp/env/jdbc/MyDataSource"/>
</bean>

Object not adhering to the JavaBeans spec

Consider Properties objects. In Spring we have the possibility to configure properties by using the tags. If we add a setter to our TestBean class that takes a Properties object, we can wire it up as follows:

<bean class="example.TestBean">
  <!-- results in a call to setPropertiesSetter(props) -->
  <property name="propertiesSetter">
    <props>
      myName=Alef
      yourName=reader
    </props>
  </property>
</bean>

Pretty easy you might find this. There’s one drawback however. If we need the properties object in more than one place, we are not able to reference it using the normal features. In other words, the Properties object passed to the TestBean isn’t a first-class citizen in our Spring application context. It’s also not possible to ‘move’ the XML element the root level and assign an id to it. Again, the FactoryBean provides a solution. Consider the following (again simplified version) of the PropertiesFactoryBean (part of Spring):

public class PropertiesFactoryBean implements FactoryBean {
 
  private Properties props;
 
  public void setProperties(Properties props) {
    this.props = props;
  }
 
  public Object getObject() {
    Properties p = new Properties(props);
    return p;
  }
}

Now we have the possibility to define a top-level Properties object and dependency inject it into more than just one bean:

<bean class="example.TestBean">
  <!-- results in a call to setPropertiesSetter(props) -->
  <property name="propertiesSetter" ref="properties/>
</bean>
 
<bean id="properties" class="example.PropertiesFactoryBean">
  <property name="properties">
    <props>
      myName=Alef
      yourName=reader
    </props>
  </property>
</bean>

Small review of what FactoryBeans Spring provides

As we’ve seen, FactoryBeans provide a level of indirection that comes in quite handy when we need to dependency inject objects that can’t just be created by the standard features of the Spring DI container. The FactoryBean removes the need to write plumbing code such as creating new InitialContext objects, loading of Properties (whereever they come from). Out-of-the-box Spring already provides a whole league of FactoryBeans you can use to instantiate complex objects such as the PropertiesFactoryBean and the JndiObjectFactoryBean we’ve already reviewed in the examples above. The following is a (non-exhaustive) list of other FactoryBeans Spring provides with a small exaplanation of what they can be used for:

  • JndiObjectFactoryBean - retrieves JNDI objects from a JNDI context
  • ListFactoryBean - creates List instances (as first-class citizens in a Spring context) where you have the option to specify the type of List you want to use
  • MapFactoryBean - same as the ListFactoryBean but this one creates Maps
  • SetFactoryBean - idem
  • TimerFactoryBean - creates java.util.Timer objects and takes care of all the necessary configuration
  • ServletContextAttributeFactoryBean - retrieves attributes from a ServletContext (works in web-app contexts only
  • WebSphereTransactionManagerFactoryBean - retrieves the WebSphere transaction manager (uses WebSphere proprietary APIs)
  • WebLogicServerTransactionManagerFactoryBean - retrieves the WebLogic transaction manager
  • And many more

Update: corrected small mistake with one of the examples where the FactoryBean said it was a singleton, but it wasn’t. Thanks to Arjen

14 Responses to “Using FactoryBeans to create the ‘uncreatable’”


  1. 1 Alexander Jun 14th, 2006 at 6:18 pm

    Very nice article, thanks for putting this all together

  2. 2 keesn Mar 13th, 2007 at 9:30 am

    where is the xml configurations..
    I can’t see the xml codes..maybe it’s caused by ”
    Please fix it. I don’t want to see xml code by Alt + V -> C

  3. 3 keesun Mar 13th, 2007 at 9:33 am

    where is the xml configurations..
    I can’t see the xml codes..maybe it’s caused by angle brackets
    Please fix it. I don’t want to see xml code by Alt + V -> C

  4. 4 Mohan Apr 25th, 2007 at 4:08 pm

    The xml configurations are not visible.

    READERS: If you want to see xml, do a view source and there they are burried in <pre> tags.

  5. 5 Nicholas Jul 24th, 2007 at 3:18 pm

    Very good explanation on the difference of FactoryBean and BeanFactory… thanks : )

  6. 6 tannoy Sep 17th, 2007 at 5:39 pm

    great stuff. this is key to understanding how Spring EhCacheFactoryBean works.

  7. 7 legege Jan 11th, 2008 at 6:47 am

    I have this problem: a bean with a getObjectsSet() returning an empty set of objects. There is a setObjectsSet(Set), but this method is protected. Normally, I would use getObjectsSet().add(..). How can I do that in Spring? I’ve try to set a policy for the security manager, but it doesn’t work. I still get the NotWritablePropertyException exception.

  8. 8 rarViardFex Feb 21st, 2008 at 2:49 am

    Just definitely I disconnected the eva lagoria nude profitable supposedly and female celebs sufficiently came in.

  9. 9 Gautam Mar 23rd, 2008 at 11:43 pm

    One of the very few articles written with very simple examples. Nice article.

  10. 10 Daniel Jun 16th, 2008 at 5:17 pm

    I’m thinking this problem for quite a long time. Sometimes I use factory-method to work around it but not so elegant. I think you give quite a good answer. Nice articel.

  1. 1 spiros.blog() » Blog Archive » Explaining Spring Framework’s FactoryBean Pingback on Jul 3rd, 2005 at 7:05 am
  2. 2 A Couple of Dutch Rants » Blog Archive » Spring instantiation strategies Pingback on Jul 3rd, 2005 at 1:31 pm
  3. 3 Mallim Ink (Beta) » Blog Archive » Spring FactoryBeans Pingback on Jul 4th, 2005 at 3:55 pm
  4. 4 Spring Framework’s FactoryBean Pingback on Dec 22nd, 2008 at 2:22 pm

Leave a Reply