Programmatically Build a Spring Application Context

January 14, 2007 – 14:56 | java, spring

The new BeanDefinitionBuilder class added in Spring 2.0 allows an XML-less way to build application contexts programmatically. Can be very useful for, say, creating quick testing setups in one of those script languages.

  1. GenericApplicationContext ctx = new GenericApplicationContext();
  2.  
  3. BeanDefinitionBuilder builderA = BeanDefinitionBuilder
  4.     .rootBeanDefinition(BeanA.class)
  5.     .addPropertyValue("name", "Joe");
  6. ctx.registerBeanDefinition("bean-a", builderA.getBeanDefinition());
  7.  
  8. BeanDefinitionBuilder builderB = BeanDefinitionBuilder.rootBeanDefinition(BeanB.class)
  9.     .addPropertyReference("refA", "bean-a");
  10. ctx.registerBeanDefinition("bean-b", builderB.getBeanDefinition());
  11.  
  12. ctx.getBean("bean-b");

The sample code above creates two bean definitions, the second one referencing the first.

Trackback from your site, or follow the comments in RSS.
  1. 14 Responses to “Programmatically Build a Spring Application Context”

  2. I would have thought the XML configuration would be easier to set-up than programming it in Java or even some other script.
    I think that a programmatic configuration is warranted where a level of dynamic configuration may be required, for example, driven from a database. This could be in combination with a base XML configuration.

    By Simon Cition on Jan 14, 2007

  3. While for simple cases the XML configuration is simpler you might find that in cases where you have an enterprise application where it gets customized on a per deployment basis that the programmatic approach offers a lot more flexibility and capabilities than you could do with the XML option. I was working on some issues at my previous job about trying to build a custom ApplicationContext and this sort of thing comes in very handy vs. trying to figure out which XML files to load and so forth. Each option has its uses.

    If you’re building a hosted app or single deployment type apps (i.e. desktop) there are probably very few areas I would use this for unless I was loading a lot of smaller ApplicationContexts or child contexts where they were dynamic based on say, user or account settings.

    However, coding is like the English language. There’s always an exception to every rule.

    By Mike Bosch on Jan 15, 2007

  4. Hi,

    i am using the programmatic approach for bean creation to create a test harness which has its own XML language whose xsd is registered with Spring. Every thing is working perfectly but i was wondering what will happen when thousands of test cases will be run together. Each test case will create its own object and there will be a large number of objects in memory. Will this cause a problem ? Any Thoughts ? work arounds ?

    By Nirav Gosalia on Jul 16, 2007

  5. @Nirav,
    Are all thousands of test cases actually going to run concurrently? Usually test cases are executed in sequence and whatever objects one test case holds are gc’ed after the case is torn down.

    By Jing Xue on Jul 17, 2007

  6. I would just like to mention that I’m currently using this approach to load dynamically generated (from a database) groovy scripts. I found the code listed above HIGHLY useful, although I ran across one small problem with the ScriptFactoryPostProcessor … you MUST ensure you call ctx.refresh(); after declaring your beans

    I’ve included the code for the curious.

    //XLogger.java
    package com.xiotl.xdb.test;

    public interface XLogger {
    void log(String msg);
    }

    //Test.java
    package com.xiotl.xdb.test;

    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.context.support.GenericApplicationContext;
    import org.springframework.scripting.support.ScriptFactoryPostProcessor;

    public class Test {

    public static void main(String[] args) {

    //Declare the ApplicationContext
    GenericApplicationContext ctx = new GenericApplicationContext();

    //Define and register the post processor
    BeanDefinitionBuilder bdb1 = BeanDefinitionBuilder
    .rootBeanDefinition(“org.springframework.scripting.support.ScriptFactoryPostProcessor”)
    .setLazyInit(false);
    ctx.registerBeanDefinition(“scriptPostProcessor”, bdb1.getBeanDefinition());

    //define the script location… in my case it is inline,
    // but any standard classpath:/package/script.groovy style location can be used
    String location = ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + “package com.xiotl.xdb.test\n” +
    “\n” +
    “import org.apache.log4j.Logger\n” +
    “\n” +
    “class Scratch implements XLogger {\n” +
    ” private static Logger logger = Logger.getLogger(\”XLogger\”);\n” +
    “\n” +
    ” public void log(String message) {\n” +
    ” logger.info(message);\n” +
    ” }\n” +
    “}”;
    //define and register the groovy bean
    BeanDefinitionBuilder bdb2 = BeanDefinitionBuilder
    .rootBeanDefinition(“org.springframework.scripting.groovy.GroovyScriptFactory”)
    .addConstructorArg(location);
    ctx.registerBeanDefinition(“groovyLogger”, bdb2.getBeanDefinition());
    //refresh the context
    ctx.refresh();
    //get the bean
    XLogger xlog = (XLogger)ctx.getBean(“groovyLogger”);
    //test the bean
    xlog.log(“A Message from Groovy”);
    }

    }

    By Edison Gieswein on Oct 5, 2007

  7. This is a great example. It is nice to see how to do this.

    I do have one question though. Is there a way to do a hybrid approach where you define some of the configuration in xml and some of it programmatically as in your example?

    I know it sounds like a strange request, but I do have some code where it would be very useful.

    By Mike on Aug 5, 2008

  8. Re: hybrid approach

    I am trying to understand it as well. It looks like calling refresh() is mandatory on any context if new bean definitions were registered. As a result, the whole configuration is reloaded and singletons are recreated.

    For plugin-like purposes I want to be able to append a new bean on-the-fly using beans from a static XML configuration as dependencies. I have not googled anything like that. Most links are about OSGI :(

    By Nick on Sep 2, 2008

  9. @Nick, you could try loading the “core” beans and the “plugin” beans into two different contexts (from two sets of XML files), and set the core context as the parent of the plugin one.

    By Jing Xue on Sep 3, 2008

  10. Hi!
    I was going through your post regarding programmatically creating ApplicationContext. On this i have a question regarding how to set a map property on any programmatically created bean.

    Regards,

    sanjeev

    By sanjeev kumar on Jan 12, 2009

  11. How would you handle scoped proxy using this method? For example suppose I want to have a session scoped bean that needs to be injected into a singleton where it would require , will the programmatic approach support this?

    By Aftab on Apr 21, 2009

  12. @Aftab,

    Probably not with the BeanDefinitionBuilder, but you can use the raw BeanDefinition API to achieve this.

    By Jing Xue on May 2, 2009

  13. I¡¦ve been exploring for a bit for any high-quality articles or weblog posts on this sort of house . Exploring in Yahoo I eventually stumbled upon this website. Reading this info So i am glad to show that I’ve a very excellent uncanny feeling I found out exactly what I needed. I most definitely will make certain to do not forget this site and give it a look regularly.

    By Edris Davos on May 19, 2011

  1. 2 Trackback(s)

  2. Jan 9, 2009: toniBlog » links for 2009-01-09
  3. Jul 10, 2012: Declaring Spring Programmatically | thekua.com@work

Post a Comment