While developing a Web App using Spring little things can take a lot of time to resolve. At the end they may appear to be very simple, and you may ask your self “how could I not think of it before – it is so obvious!”. Well, yea, it is obvious, but you just have to know it! One of the places that helps you to solve the “obvious” (and not so obvious), so you do not have to spin your wheels is, with no doubts, the spring forum. However you need to know the right search criteria to find what you need.
Here I just want to share something small but important about the visibility of Spring Contexts in a Web App.
Looking at org.springframework.web.servlet.DispatcherServlet API notice this:
“A web application can define any number of DispatcherServlets. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. Only the root application context as loaded by ContextLoaderListener, if any, will be shared.”
This brings an interesting point – in a Spring Web App you have one root application context which is private, and many dispatcher servlet application contexts which are children of the root application context:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/classes/applicationContext.xml /WEB-INF/classes/otherContext.xml </param-value> </context-param> ... <servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> ... <servlet> <servlet-name>dispatcher-servlet-number-x</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> |
In the above, everything that is defined in “contextConfigLocation” is your root application context. Every “dispatcher-servlet-number-x” (“dispatcher-servlet-number-1”, “dispatcher-servlet-number-2”, etc..) would represent a child application context which will see (have the visibility to) all the beans from the parent (root) context, but will not see any of the beans defined by its siblings – another dispatcher servlet contexts.
The only gotcha in the above visibility is BeanFactoryPostProcessor / BeanPostProcessor (s) – like “PropertyPlaceholderConfigurer” for example. These guys apply ONLY to beans in its own context. For example, if you have PropertyPlaceholderConfigurer defined in the root application context, none of root’s children will be able to use it (see) the ${properties}.
Here is the semi-official version “why” from Juergen (Spring Lead Developer):
“PropertyPlaceholderConfigurer is an implementation of the BeanFactoryPostProcessor interface: This interface and its sibling BeanPostProcessor just apply to the BeanFactory that defines them, that is, to the application context that defines them.
If you combine multiple config files into a single contextConfigLocation, a PropertyPlaceholderConfigurer defined in any of the files will apply to all of the files, because they are loaded into a single application context.
However, a DispatcherServlet has its own application context, just using the root web application context as parent. Therefore, it needs to define its own BeanFactoryPostProcessors and/or BeanPostProcessors, in this case its own PropertyPlaceholderConfigurer.”
Happy Springing!