388
  • Are applicationContext.xml and spring-servlet.xml related anyhow in Spring Framework?
  • Will the properties files declared in applicationContext.xml be available to DispatcherServlet?
  • On a related note, why do I need a *-servlet.xml at all? Why is applicationContext.xml alone insufficient?
Vy Do
  • 46,709
  • 59
  • 215
  • 313
user448070
  • 4,023
  • 3
  • 16
  • 11
  • 2
    See this as well. http://stackoverflow.com/questions/11708967/what-is-the-difference-between-applicationcontext-and-webapplicationcontext-in-s – Sanghyun Lee May 13 '15 at 07:22

6 Answers6

440

Spring lets you define multiple contexts in a parent-child hierarchy.

The applicationContext.xml defines the beans for the "root webapp context", i.e. the context associated with the webapp.

The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet's app context. There can be many of these in a webapp, one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml for servlet spring2).

Beans in spring-servlet.xml can reference beans in applicationContext.xml, but not vice versa.

All Spring MVC controllers must go in the spring-servlet.xml context.

In most simple cases, the applicationContext.xml context is unnecessary. It is generally used to contain beans that are shared between all servlets in a webapp. If you only have one servlet, then there's not really much point, unless you have a specific use for it.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 32
    why would you have multiple spring servlets ? – NimChimpsky Aug 14 '12 at 09:59
  • About your comment _All Spring MVC controllers must go in the spring-servlet.xml context._, where can I find in the official Spring reference? – Lee Chee Kiam Nov 29 '12 at 09:27
  • @CKLee, when I move them into the root application context, Spring MVC does not process any `@RequestMapping`. At least, that's what I remembered, and a quick test confirmed that. However, [some have no issues](http://stackoverflow.com/questions/10019426/spring-transactional-not-working/10021874#comment12812351_10019426) moving the scanning of `@Controller` into the root context, it seems, so I might be wrong. – Arjan Feb 03 '13 at 12:43
  • 5
    mighty potent answer (because of succinctness) – amphibient Mar 15 '13 at 16:44
  • 35
    @NimChimpsky it is sometimes useful to separate parts of your application that could otherwise conflict in the same context. As an example you may have ReST services and standard views, you may then have different view resolvers or security concerns for the services as to the views. – Brett Ryan Apr 03 '13 at 17:19
  • 12
    People should see this answer before reading documentation and developing apps! In normal cases there is no need to have ContextLoaderListener and contextConfigLocation at all, just DispatcherServlet! – ruruskyi Jun 28 '13 at 13:11
  • 24
    In many tutorials contextConfigLocation contains dispatcher-servlet.xml as well as DispatcherServlet. This causing beans to be initialized twice! – ruruskyi Jun 28 '13 at 13:24
  • 1
    ruruskyi The statement about putting everything into one context is only skaffman's opinion, the official STS team approach is described in Raje's answer. I see no reason to put everything together especially because AOP do not play well with controller. If you use Spring Security for example using method security with dispatcher servlet is strongly discouraged. This answer is four years old after all. – Boris Treukhov Jan 03 '14 at 13:54
  • 2
    @NimChimpsky I like your question and I upvoted it. *why would you have multiple spring servlets ?* It took me a while to figure out this context structure and having done so I am left wondering if anyone actually uses it. For myself, if I have two services I will put them in different .war files so that I can deploy them separately. It seems like someone went to a lot of trouble to create this servlet/mvc "feature". But for me it is a overly complex with a low amount of utility. – Matt Friedman May 06 '14 at 21:41
  • @Matt Friedman: even if you do not have multipe servlets there are reasons to use the two contexts: see http://stackoverflow.com/questions/9016122/contextloaderlistener-or-not – Ralph May 24 '16 at 10:31
  • where does web.xml comes into picture then? – Nisarg Patil Sep 20 '18 at 06:30
  • 1
    "Beans in `spring-servlet.xml` can reference beans in `applicationContext.xml`". Can you explain how? Link to any example? – MsA Oct 09 '18 at 16:30
110

Scenario 1

In client application (application is not web application, e.g may be swing app)

private static ApplicationContext context = new  ClassPathXmlApplicationContext("test-client.xml");

context.getBean(name);

No need of web.xml. ApplicationContext as container for getting bean service. No need for web server container. In test-client.xml there can be Simple bean with no remoting, bean with remoting.

Conclusion: In Scenario 1 applicationContext and DispatcherServlet are not related.

Scenario 2

In a server application (application deployed in server e.g Tomcat). Accessed service via remoting from client program (e.g Swing app)

Define listener in web.xml

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

At server startup ContextLoaderListener instantiates beans defined in applicationContext.xml.

Assuming you have defined the following in applicationContext.xml:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

The beans are instantiated from all four configuration files test1.xml, test2.xml, test3.xml, test4.xml.

Conclusion: In Scenario 2 applicationContext and DispatcherServlet are not related.

Scenario 3

In a web application with spring MVC.

In web.xml define:

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

When Tomcat starts, beans defined in springweb-servlet.xml are instantiated. DispatcherServlet extends FrameworkServlet. In FrameworkServlet bean instantiation takes place for springweb . In our case springweb is FrameworkServlet.

Conclusion: In Scenario 3 applicationContext and DispatcherServlet are not related.

Scenario 4

In web application with spring MVC. springweb-servlet.xml for servlet and applicationContext.xml for accessing the business service within the server program or for accessing DB service in another server program.

In web.xml the following are defined:

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

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

At server startup, ContextLoaderListener instantiates beans defined in applicationContext.xml; assuming you have declared herein:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

The beans are all instantiated from all four test1.xml, test2.xml, test3.xml, test4.xml. After the completion of bean instantiation defined in applicationContext.xml, beans defined in springweb-servlet.xml are instantiated.

So the instantiation order is: the root (application context), then FrameworkServlet.

Now it should be clear why they are important in which scenario.

Community
  • 1
  • 1
abishkar bhattarai
  • 7,371
  • 8
  • 49
  • 66
54

One more point I want to add. In spring-servlet.xml we include component scan for Controller package. In following example we include filter annotation for controller package.

<!-- Scans for annotated @Controllers in the classpath -->
<context:component-scan base-package="org.test.web" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

In applicationcontext.xml we add filter for remaining package excluding controller.

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
butallmj
  • 1,531
  • 4
  • 14
  • 21
Raje
  • 3,285
  • 15
  • 50
  • 70
  • 9
    why ? Why not just scan the whole thing one time ? – NimChimpsky Aug 14 '12 at 09:57
  • 3
    @NimChimpsky You have to scan `@Controller` beans in servlet context (required by Spring MVC). – Tuukka Mustonen Nov 21 '12 at 12:22
  • 3
    Why not can the whole thing twice? Why include/exclude? – Rylander Jul 05 '13 at 16:26
  • 8
    One should also add use-default-filters="false" attribute in spring-servlet.xml – Rakesh Waghela Feb 25 '14 at 09:51
  • 4
    Rakesh Waghela has point. Without that attribute Controller beans will be created twice. Firstly in appContext and secondly in servletContext – UltraMaster Feb 26 '14 at 18:54
  • 2
    @MikeRylander this will create chaos as the beans will be scanned and created twice. For example if you have DAO/Repository beans they will be duplicated and those that are in the servlet contexts will run without transactions(as transaction AOP is usually done only declared in the root context) or Spring method security (if security is not declared in the servlet context explicitly) – Boris Treukhov May 06 '16 at 16:51
  • Why not create separate package for each category? and `com.abc.controller`, `com.abc.dao` then don't need to filter? – Asif Mushtaq Sep 16 '18 at 06:58
12

In simple words,

applicationContext.xml defines the beans that are shared among all the servlets. If your application have more than one servlet, then defining the common resources in the applicationContext.xml would make more sense.

spring-servlet.xml defines the beans that are related only to that servlet. Here it is the dispatcher servlet. So, your Spring MVC controllers must be defined in this file.

There is nothing wrong in defining all the beans in the spring-servlet.xml if you are running only one servlet in your web application.

Vy Do
  • 46,709
  • 59
  • 215
  • 313
Krishna
  • 7,154
  • 16
  • 68
  • 80
  • 3
    I can define all the beans in spring-servlet.xml, but there also should be applicationContext.xml that may be empty (without beans) in this case. Correct? – Mikhail Kopylov Dec 04 '15 at 06:13
6

In Servlet technology if you want to pass any input to a particular servlet then you need to pass in init param like below code.

 <servlet>
    <servlet-name>DBController</servlet-name>
    <servlet-class>com.test.controller.DBController</servlet-class>
    <init-param>
        <param-name>username</param-name>
        <param-value>John</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DBController</servlet-name>
    <url-pattern>/DBController</url-pattern>
</servlet-mapping>

If you want to pass some in put that is common for all servlets then that time you need to configure context param. Example

 <context-param>
    <param-name>email</param-name>
    <param-value>admin@example.com</param-value>
</context-param>

SO exactly like this when ever we are working with Spring MVC we need to provide some information to Predefined servlet provided by Spring that is DispatcherServlet through init param. So the configuration is as fallows, here we are providing the spring-servlet.xml as init parameter to DispatcherServlet.

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
              http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>Spring MVC App</display-name>

    <servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
</web-app>

Again we need some context param. That is applicable for whole application. So we can provide the root context that is applicationcontext.xml The configuration is like this:

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationcontext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
Rajanikanta Pradhan
  • 580
  • 1
  • 8
  • 12
4

Application contexts provide a means for resolving text messages, including support for i18n of those messages. Application contexts provide a generic way to load file resources, such as images. Application contexts can publish events to beans that are registered as listeners. Certain operations on the container or beans in the container, which have to be handled in a programmatic fashion with a bean factory, can be handled declaratively in an application context. ResourceLoader support: Spring’s Resource interface us a flexible generic abstraction for handling low-level resources. An application context itself is a ResourceLoader, Hence provides an application with access to deployment-specific Resource instances. MessageSource support: The application context implements MessageSource, an interface used to obtain localized messages, with the actual implementation being pluggable

Sujata
  • 151
  • 1
  • 1
  • 5