I have an ear package that contains one jar with common objects and two war webapps that I'd like to use the common jar. I've setup the configuration to use application wide context via ContextLoaderListener and webapp contexts separately for DispatcherServlet.
The setup of my demo app is roughly the following
common.jar
contains applicationContext.xml and beanRefContext.xml, which are supposed to be application (ear) wide context. The files are like below. shared namespace is where the shared bean is located.
applicationContext
<beans>
<!-- namespace etc declarations omitted -->
<context:annotation-config />
<context:component-scan base-package="study.spring.multicontext.shared" />
</beans>
beanRefContext.xml
<beans>
<!-- namespace etc declarations omitted -->
<bean id="sharedContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>classpath*:applicationContext.xml</value>
</list>
</constructor-arg>
</bean>
</beans>
webapp1
andwebapp2
are Spring MVC applications packaged as separate wars with web.xml file like below<web-app> <context-param> <param-name>parentContextKey</param-name> <param-value>sharedContext</param-value> </context-param> <context-param> <param-name>locatorFactorySelector</param-name> <param-value>classpath:beanRefContext.xml</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dos</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dos-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dos</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
and xx-servlet.xml like for webapp specific context. web namespace is where the controllers are located.
<beans>
<!-- namespace etc declarations omitted -->
<context:component-scan base-package="study.spring.multicontext.web"/>
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="suffix" value=".jsp"/>
</bean>
</beans>
The shared bean is @Autowired in normal fashion in Controller classes
@Autowired MySharedBean mySharedBean
ear package contains both wars and jar, and structure is like
ear | |--common.jar | |--META-INF | |--applicationContext.xml | |--beanRefContext.xml | |--webapp1.war | |--WEB-INF | |--xx-servlet.xml | |--web.xml | |--webapp2.war | |--WEB-INF | |--xx-servlet.xml | |--web.xml
The problem is that there will still be two instances of the bean. One for each controller/webapp, since there's only one Controller in each of the wars. I have tried to twiddle with the configuration, but no matter what I do, I either get zero instances or two instances.
I checked the references with Eclipse MAT from a memory dump, and there are actually 4 instances, but I guess the two are for Spring internal use. Anyway, from there it's clearly visible that each controller has it's own instance.
I've read numerous of blog posts, discussion forums, etc where they say that this should be as simple as this. Some suggest JNDI, but as I've understood, this should be possible without it.
And it's not possible to combine the wars and bundle the jar inside. As it might work for this demo app, the real life case I'm working with does not allow this.
Any help on this matter is highly appreciated. Thanks in advance.
SpringSource example from 2007 for Spring 2.X that does the same but with different configuration. A bit outdated and looking for a Spring 3.X based solution, as dscribed in the bounty description.