RSS
 

Access Spring context from static methods

22 Jan

In this post I will present a very simple example that attempts to access an existing Spring application context from a class that has nothing to do with the Spring context. For example from a static method of a class. This is, of course, quite trivial, but I might make use of this little technique in some next posts about Spring, so I think it is due to first start with this small example.

Therefore, what I want to do is to have an up-and-running application context, and access the beans in that context from a static method. The best approach is to never have to do this. In an ideal case, all your classes are Spring beans, and therefore subjects to autowiring and dependency injection. However, from time to time you need to write a completely independent class, that needs to access some Spring beans.

The approach that I found it works quite ok is to have an ApplicationContextProvider. This class is picked by Spring as a bean, and since it implements ApplicationContextAware it will receive the application context. Once it does that, it stores the context in a static field, and then all the other non-Spring classes can get their hands on the context by calling some static getContext() method. Here is the class:

public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext context;

    public static ApplicationContext getContext() {
        if ( context != null ) {
            return context;
        } else {
            throw new IllegalStateException( "The Spring application context is not yet available. " +
                                                     "The call to this method has been performed before the application context " +
                                                     "provider was initialized" );
        }
    }

    @Override
    public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException {
        if ( context == null ) {
            ApplicationContextProvider.context = applicationContext;
        } else {
            throw new IllegalStateException( "The application context provider was already initialized. " +
                                                     "It is illegal to place try to initialize the context provider twice or create " +
                                                     "two different beans of this type (even if the contexts are different)" );
        }
    }
}

My context XML file looks like the following:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="messagePrinter" class="zendo.playground.spring.MessagePrinter"/>
    <bean class="zendo.playground.spring.ApplicationContextProvider"/>

</beans>

And finally, the test classes that show how to use the ACP:

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( locations = "TestStaticAccess.xml" )
public class TestStaticAccess {
    @Test
    public void test() {
        StaticAccess.doSmt();
    }
}

class StaticAccess {
    public static void doSmt() {
        MessagePrinter printer = (MessagePrinter) ApplicationContextProvider.getContext().getBean( "messagePrinter" );
        printer.print();
    }
}

As one can see from above, the ACP guards against trying to access the context before it was initialized (like, for example, calling the ACP from the static constructor of a class, long before the Spring context was started) and against the usage of the ACP in two different Spring contexts.

Please mind that I am not referring here to the case when you are in a servlet, for example, and want to access the Spring context. For this, you can safely use the alternative provided by Spring: WebApplicationContextUtils

http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/context/support/WebApplicationContextUtils.htmlWeb
 
1 Comment

Posted in Spring

 

Leave a Reply

 

 
  1. Ehcache event listeners as Spring beans « Bogdan Mocanu

    February 2, 2011 at 9:35 pm

    [...] statically, using the simple pattern with the ApplicationContextProvider that I presented in a previous post. Ehcache creates an instance of the factory, and when it asks for the listener, the factory fetches [...]