Senthadev

{ Think. Ask Why. Do it. }


Sharing Spring container between modules in a web application

This note is about sharing a Spring container between modules in a web application.
Why do I want to have a common container?, lets look at the below given scenario:

Lets say that we a web application, mywebapp.war, which was developed to provide business services via different transports such as SOAP/XML and RMI. RMI is based on pure Java and data is in binary. On the other hand, SOAP is for clients which understand HTTP and XML.
This web application uses Spring container to manage the beans and transactions along with JPA for database CRUD operations. To provide SOAP service, AXIS 1.4 has been used.
Now core servlet, which handles the CRUD operations, and Axis servlet both must share the Spring container.

Lets look at how to achieve it.

In mywebapp.war, web.xml


<context-param>
<param-name>locatorFactorySelector</param-name>
<param-value>classpath:beanRefFactory.xml</param-value>
</context-param>
<context-param>
<param-name>parentContextKey</param-name>
<param-value>myShareSpringContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-config-empty.xml
</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

  

In the above web.xml,

“locatorFactorySelector” will be pointing to the xml file which contains the Spring bean configuration file name. In our example, file name is beanRefFactory.xml. If we look at the contents of this file:



<?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="myShareSpringContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>spring-config.xml</value>
</list>
</constructor-arg>
</bean>

</beans>

  

“parentContextKey” parameter, we have assigned “myShareSpringContext”.

For the “contextConfigLocation” parameter we have specified an empty Spring configuration xml file since we will be loading the Spring context from beanRefFactory.xml. In our example the file name is “spring-config-empty.xml”. This spring-config-empty.xml will have the following contents:



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

<beans></beans>

  

In mywebapp.war, we are loading the Spring context from the following listener “org.springframework.web.context.ContextLoaderListener”.
If we analysis listener class, it’s designed to load the new context or use an existing context.

Now looking at the Axis web service implementation, lets say in BusinessSrvSoapBindingImpl.java, Spring context is loaded as :



String locatorFactorySelector = "classpath:beanRefFactory.xml";
String parentContextKey = "myShareSpringContext";
BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
BeanFactoryReference parentContextRef = locator.useBeanFactory(parentContextKey);
context = (ApplicationContext) parentContextRef.getFactory();

//Now from the "context" object reference we can retrieve the Spring managed beans.
  

We have used “ContextSingletonBeanFactoryLocator” to retrieve the Spring container location. If we analysis this class, it has its own hashmap to store the application context. Key will be “parentContextKey” value.

Now both core Servlet and Axis SOAP will use the same Spring container rather than creating a copy for each of them.

For more information please refer following links:

1] SingletonBeanFactoryLocator and ContextSingletonBeanFactoryLocator documentations from Spring framework documentation.

2] http://slawek-zachcial.blogspot.com/2005/03/mdbstrutsspringhibernate-weblogic-way.html

2008-04-30
By @Senthadev