21

Suppose that I have a Spring Java project and I am trying to configure it as a web server servlet. Here is a stripped-down version of the web.xml file:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/generalApplicationContext.xml
    </param-value>
</context-param>

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

<servlet-mapping>
    <servlet-name>my-servlet</servlet-name>
    <url-pattern>/foo/*</url-pattern>
</servlet-mapping>

The key thing to note here is that I have specified two XML files to be loaded. One is general for my entire application, while the other is specific to the "my-servlet" servlet. For a setup with just one servlet-mapping, this wouldn't make sense. However, my project has multiple servlet-mappings and each one has specific Spring settings to them.

My Question: Which contextConfigLocation is going to be loaded first by Spring? Will it be the generalApplicationContext.xml or will it be the specificApplicationContext.xml? More importantly, does the order of loading even matter? From my debugging efforts, it seems apparent that it does because I get different errors when I move some independent Spring configuration from one file to the other.

NB: Whether or not using multiple spring configurations for multiple servlet mappings is a good practice is debatable. Same goes for using XML config instead of the new Java config. But that's not what I'm trying to ask here. Let's try to focus on my main question.

ecbrodie
  • 11,246
  • 21
  • 71
  • 120
  • the one you declared inside your DispatcherServlet not sure about it tho, `1` because of this i think . – Secondo Dec 18 '14 at 05:11
  • To get the `contextConfigLocation` / `generalApplicationContext.xml` loaded at all, you MUST have a `ContextLoaderListener` - see shazin's answer. And for a deeper understanding of what is it usefull for see this question and answers: http://stackoverflow.com/questions/9016122/contextloaderlistener-or-not – Ralph Dec 18 '14 at 05:59
  • What does NB mean? – sofs1 Mar 07 '18 at 07:17

4 Answers4

22

generalApplicationContext.xml is the one that will be loaded first because it is the ApplicationContext loaded with the ContextLoaderListener

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

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/generalApplicationContext.xml
    </param-value>
</context-param>

specificApplicationContext.xml is actually a Child Context of the Above loaded generalApplicationContext.xml and it will be a WebApplicationContext

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

<servlet-mapping>
    <servlet-name>my-servlet</servlet-name>
    <url-pattern>/foo/*</url-pattern>
</servlet-mapping>

And yes the order of loading does matter. Because when the parent context is loaded all the required dependencies must be fulfilled.

shazin
  • 21,379
  • 3
  • 54
  • 71
  • How did you named both as `ApplicationContext` and `WebApplicationContext` ? – Asif Mushtaq Sep 15 '18 at 13:49
  • Are you sure in saying "`ApplicationContext` loaded with the `ContextLoaderListener`", or its `WebApplicationContext`? I am pretty much confused. [This](https://i.postimg.cc/CLMT84KM/webappcontext.png) official doc says: "... `ContextLoaderListener` looks for a file called `/WEB-INF/applicationContext.xml` to load. Once the context files are loaded, Spring creates a `WebApplicationContext` object based on the bean definitions..." – MsA Oct 02 '18 at 13:37
  • @anir `WebApplicationContext` interface is just an extension of `ApplicationContext` [https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/context/WebApplicationContext.java](ApplicationContext). This answer is about the order of loading not the type of Application Context. – shazin Oct 02 '18 at 14:36
  • 2
    I know `WebApplicationContext` is a subtype of `ApplicationContext`. However I want to know what exactly `ContextLoaderListener` creates, `ApplicationContext` or `WebApplicationContext`. If it creates `ApplicationContext` instance, its definitely not equivalent to `WebApplicationContext`, as former does not provide functionality of later. Is it like, precisely talking, `ContextLoaderListener` creates `WebApplicationContext` which also provides functionalities of `ApplicationContext`, being subtype of it? [continued...] – MsA Oct 02 '18 at 14:49
  • 2
    [...continued] [This answer](https://stackoverflow.com/a/11817368/6357916) says it creates both `ApplicationContext` and `WebApplicationContext`. Now trying to understand what it exactly does from [source](https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/context/ContextLoaderListener.java). But its not making any sense... – MsA Oct 02 '18 at 14:50
  • 2
    [...continued] ok looking at the [source](https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/context/ContextLoaderListener.java) (also of its [supertype](https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/context/ContextLoader.java)), it seems that it creates `WebApplicationContext`. The articles explaining this topic say `ApplicationContext` out of convenience (or implicitly assuming reader will know we always meant `WebApplicationContext` ). – MsA Oct 02 '18 at 15:19
  • 2
    [...contined 4] is it like the `WebApplicaionContext` created by `ContextLoaderListener` is what [usually online articles refer](https://i.postimg.cc/s2CKv8b0/webappcontext.png) to as **"root"** `WebApplicationContext`, just to differentiate it from `WebApplicationContext`s created by `DispatcherServlet`? – MsA Oct 02 '18 at 15:36
8

The below part loads the context file and create the ApplicationContext. This context might, for instance, contain components such as middle-tier transactional services, data access objects, or other objects that you might want to use (and re-use) across the application. There will be one application context per application.

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/generalApplicationContext.xml
    </param-value>
</context-param>

The other context is the WebApplicationContext which is the child context of the application context. Each DispatcherServlet defined in a Spring web application will have an associated WebApplicationContext. The initialization of the WebApplicationContext happens like this:

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

For more details refer this and this

Community
  • 1
  • 1
Ankur Singhal
  • 26,012
  • 16
  • 82
  • 116
  • what you have written is true in most cases, but not in this one, because `ecbrodie` has no `ContextLoaderListener` in his xml or he has omitted in the question it by accident. – Ralph Dec 18 '14 at 05:57
  • I didn't post my full web.xml. I will do so as soon as I have a chance. – ecbrodie Dec 18 '14 at 13:41
  • @ankur your parent ApplicationContext is also instance of WebApplicationContext. – Tanmoy Banerjee Jun 01 '17 at 07:13
7

What better way to actually have the Spring debug logs tell you itself the order. If you want to get into the code you can also take a look at the org.springframework.web.servlet.FrameworkServlet (DispatcherServlet extends this class) Just enable the logger "org.springframework.web.servlet" to debug level in your preferred logging framework

Here is how the logs would typically look like - clearly the root context is loaded first and is set as the parent for the context heirarchy - the servlet context is loaded next.

INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/generalApplicatonContext.xml]
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 256 ms
DEBUG: org.springframework.web.servlet.DispatcherServlet - Initializing servlet 'my-servlet'
INFO :Initializing Spring FrameworkServlet 'appServlet'
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'my-servlet': initialization started
DEBUG: org.springframework.web.servlet.DispatcherServlet - Servlet with name 'appServlet' will try to create custom WebApplicationContext context of class 'org.springframework.web.context.support.XmlWebApplicationContext', using parent context [Root WebApplicationContext: startup date [Fri May 15 17:08:24 IST 2015]; root of context hierarchy
DEBUG: Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/specificApplicationContext.xml
Shailendra
  • 8,874
  • 2
  • 28
  • 37
  • is this means that "specificApplicationContext.xml" should only have configurations related to @controllers and view Resolvers? And "generalApplicatonContext.xml" will hold application level configurations like transaction managers and service beans and quartz schedulers, i mean configurations that needs to be available to all controllers, Why not we can make all configuration in "generalApplicatonContext.xml" ? – Mubasher Apr 27 '17 at 09:23
3

If you are having ContextLoaderListener in your web.xml spring will load the generalApplicationContext.xml first. This will create beans and provide them all Servlets and Filters. This xml should have the common classes, beans which are used in your application.

Later spring container will load the specificApplicationContext.xml, because you have load on startup in the servlet config. If you don't specify the load on start up, this specificApplicationContext.xml will load when the first request comes to your application with the specific url-pattern.

As your question when you move you springconfig from one config to another this will change the application resource availability to the container. If you specify the Controller beans in generalApplicationContext.xml and you don't specify them in specificApplicationContext.xml then your DispatcherServlet wont find the mappings, so you will see 404 error.

If you want to create some bean objects on-demand you can create one more servlet-config to load that specific specificConfigurationFile2.xml, and map to the url-pattern.