4

I had two questions,

In Spring MVC application, what is the purpose of having ContextLoaderListener?

Below are the my entries in web.xml, All MVC beans are defined in servlet-context.xml All database and annotation based transaction management is defined in applicationContext.xml and I'm using container managed transaction in JBoss

The trasaction manager works fine if I pass the applicationContext.xml as highlighted below as to DispatcherServlet. But I thought we should only pass the Spring MVC context info to DispatcherServlet.

If I remove the applicationContext.xml the transaction manager stops working? I'm confused what is best way of managing the context files?

Web.xml

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

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>    
        /WEB-INF/config/applicationContext.xml
        /WEB-INF/config/spring-mail.xml
    </param-value>
</context-param>
<context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>messages</param-value>
</context-param>


<servlet>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/config/servlet-context.xml
           ***/WEB-INF/config/applicationContext.xml***
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jee="http://www.springframework.org/schema/jee"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- registers all of Spring's standard post-processors for annotation-based configuration -->
<context:annotation-config />

<jee:jndi-lookup id="dataSource" jndi-name="java:OracleDS"/>


<tx:annotation-driven/>
<tx:jta-transaction-manager/>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation"
              value="classpath:com/common/model/config/sqlmapconfig.xml"/>
</bean>

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="sqlSessionFactory"/>
</bean>

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-- Scans the classpath of this application for @Components to deploy as beans -->
<context:component-scan base-package="com.xxxx"/>

<!-- Configures the @Controller programming model -->
<mvc:annotation-driven/>

<!-- Configures Handler Interceptors -->
<mvc:interceptors>
    <!-- Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de -->
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    <!--Register Request/Response Interceptor-->
    <bean class="com.xxx.common.auditor.RequestInterceptor"/>
   <!-- <bean class="com.xxx.common.interceptor.UserAuthenticationInterceptor"/>-->
</mvc:interceptors>

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>

<!-- Application Message Bundle -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="/WEB-INF/messages/messages"/>
    <property name="cacheSeconds" value="0"/>
</bean>


<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>/WEB-INF/xxxx.properties</value>
    </property>
</bean>

Thanks for you help! I know its quote long, but wanted to make myself understood better

Taran Singh
  • 583
  • 2
  • 6
  • 13

1 Answers1

14

As explained in the documentation, every dispatcher servlet has its own application context, where you typically define controllers, view resolvers, etc., and which inherits (and can override beans) from a root application context, which typically contains data source definitions, middle tier services, etc.

The ContextLoaderListener, as its documentation explains, is used to to start up and shut down Spring's root application context (from which the servlet contexts inherit).

It's also useful when you want to use Spring for your middle tier, but you don't want to use Spring MVC as your presentation layer. In this case, you only define a root application context using ContextLoaderListener.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • doesn't really answer anything apart for spring documentation link and moreover what I'm already saying that I'm separating the web and application context – Taran Singh Feb 10 '12 at 12:47
  • 6
    Your first question is: what's the purpose of ContextLoaderListener. The answer is: to start up and shut down the root application context. Your second question is: I'm confused what is best way of managing the context files. The answer is: the middle tier services should be in the root context, loaded by the ContextLoaderListener. The Spring MVC specific beans should be defined in the dispatcher servlet's context, which inherits from the root one. You have two XML files, but a single context. You should have a root context, and a servlet-scoped context. – JB Nizet Feb 10 '12 at 12:58
  • thanks ! OK, I have the listener with root context contextConfigLocation /WEB-INF/config/applicationContext.xml /WEB-INF/config/spring-mail.xml doesn't it initialize not the root context? And wouldn't the dispatcher servlet will initialize the web-context? Further, why the transaction manager stops working if I don't include the application context info in Dispatcher Servlet? – Taran Singh Feb 10 '12 at 14:45
  • 1
    Won't having two contexts duplicate the beans in the root context if the controllers in the dispatcher context require beans from the root context? – Derek Mahar Jan 15 '16 at 20:48