How to get Spring Application Context in Spring Framework

Discussions

Web tier: servlets, JSP, Web frameworks: How to get Spring Application Context in Spring Framework

  1. Check out these updated Tutorials for Spring 3 and Hibernate 3.x
    __________________________________________________

    Hi,

    I was playing Spring framework for couple days and got confused about the application context access.

    To my understanding, in order to get a bean, you should get the application context and call getBean. In the servlet layer it is easy, all you need to do is

    // test the spring framework
    ServletContext servletContext =this.getServletContext();

    WebApplicationContext wac = WebApplicationContextUtils.
    getRequiredWebApplicationContext(servletContext);

    User user = (User)wac.getBean("user");


    But if you are in the business layer, how do you reach the application context? The Spring reference has example of loading the xml file directly. But that is not a good way to do it. I just want to get the context and call getBean.

    Thanks for the help.
    -- Jin

    Recommended Books for Learning Spring

    Spring in Action  ~ Craig Walls
    Spring Recipes: A Problem-Solution Approach  ~ Gary Mak
    Professional Java Development with the Spring Framework ~ Rod Johnson PhD
    Pro Java EE Spring Patterns: Best Practices and Design Strategies ~ Dhrubojyoti Kayal

    Threaded Messages (9)

  2. more info[ Go to top ]

    Of course I need to put spring.jar in WEB-INF/lib and write the WEB-INF/applicationContext.xml, as well as telling the servlet container to load it in web.xml.

    applicationContext.xml example:

    <?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="user" class="app.businessBean.User">
    <property name="account"><ref bean="account"/></property>
    </bean>

    <bean id="account" class="app.businessBean.Account">
    <property name="order"><ref bean="order"/></property>
    </bean>

    <bean id="order" class="app.businessBean.Order" singleton="false">
    <property name="totalAmt"><value>10.3</value></property>
    </bean>

    </beans>

    And the web.xml hook up example:

    <servlet>
    <servlet-name>context</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
  3. Re: more info[ Go to top ]

    Simply do this in your business layer POJO that is already wired in your spring context...you simply implement the setter for the ApplicationContext... [code] public class MyFoFingerServiceImpl implements ApplicationContextAware, MyFoFingerService{ private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext){ this.applicationContext = applicationContext; } public void doStuff(){ SomeService someService = (SomeService)applicationContext.getBean("someService"); } } [/code]
  4. coupling to spring[ Go to top ]

    Although the business object could implement the ApplicationContextAware interface, surely this tightly couples POJOs to Spring which I thought was not a desirable effect. I am just looking into Spring now but I thought Spring was intended to release business objects from the 'plumbing'?
  5. Why not put a setter method on your business object and use IOC to provide your business object a reference to whatever object it depends on.
  6. To access the current ServletContext (used by WebApplicationContextUtils) in your (Spring managed) bean, you have to implement the org.springframework.web.context.ServletContextAware interface.

    Generally I agree with Frank.
  7. Frank, thanks for the reply.

    I agree it could be done with getter and setter in the business service object to any beans it needs to reference to. And in fact if the beans are directly related to the particular service the business object offer in a method, we might just pass in as parameters.

    But then it might be quite busy on the servlet level as it retrieves the business object from the spring's application context and then has to call all the getters and setters so the business service object need reference too.

    I would prefer only getting strictly the beans the business service object needs for business operation and let the business service object resolve other non-critical, cross application objects on its own. To my understand Spring is cross application and provide that bean lookup functionality in all layers.

    On solution I can think of is creating a InitAction that runs at servlet container startup. And it stores the Spring application context in a static object for global access. In this way, all layers can reach the Spring application context and call getBean for whatever bean they want.

    But still I would prefer the Spring framework to provide that functionality. I was a bit surprise it does not have something like ApplicationContextUtil.getContext
  8. Why don't you use WebApplicationContextUtils.getWebApplicationContext(currentServletContext) in your business objects? The implementation of the ServletContextAware interface gives you a setServletContext(ServletContext servletContext) method, so you can access or store the servlet context locally in your bean (e.g. a business facade).
  9. reply[ Go to top ]

    Hi Thomas,

    Thanks for the response. But my big concern is not wanting the servlet context to leaked into business and lower layers. Let's say in the DAO layer I want to have access to a global object defined in the applicationContext.xml, I do not want to pass the servlet context down so I could use the WebApplicationContextUtil.getWebApplicationContext(currentServletContext). And I do not want my bean to implements the WebApplicatonContextAware interface too.

    I could store the application context in a static object for global access in an init servlet but that is not very framework oriented. I prefer to let the Spring framework to provide that place where I could easily access the application context in different non-web layers and more importantly, know how to access this application context from application to application as it is a well defined place to get the application context instead of letting each developer to design his/her own place to hold it.

    Thanks
    -- Jin
  10. reply[ Go to top ]

    Jin,

    One of the problems with the approach you described is that you would then have code throughout your business objects looking up other business objects through the Spring context, possibly even hardcoded lookup names. Could get messy. Anyway, Spring does this for you by wiring up your dependencies when the Context is loaded. So your actually writing code in your business objects that Spring can do for you. This type of code is of no real value to your business objects. Spring provides you with the ability to keep this kind of plumbing code out of your business objects letting the developers focus on the business logic. Spring does provide a way to load a Context defined in an xml file through the XMLApplicationContext. This can be very useful when unit testing your business layer outside of the Web container.