I've looked at a bunch of sample projects and I can't seem to tease out a common best practice. I've seen Spring bean config files sometimes go in the src/main/webapp/WEB-INF
directory. I've seen this in conjunction with with a Servlet definition in web.xml
like this:
<servlet>
<servlet-name>my-stuff</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/my-stuff-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
But I've also seen bean config files included within web.xml
top level -- i.e. outside of a Servlet. What does this mean? Is this for cross-Servlet beans? Sometimes it's in the src/main/webapp/WEB-INF
directory and sometimes it's in src/main/resources
. Also I've seen other bean config files defined in WAR modules with just about everything in src/main/resources
.
I've read and re-read the Spring documentation, but the only convention I found is that by default a Servlet context config file should be in the src/main/webapp/WEB-INF
directory named {servlet-name}-servlet.xml
.
So what's the best practice and why?
Application contexts in Spring can form hierarchies where child context has access to beans defined in parent context.
A typical Spring MVC web application contains a hierarchy with two levels:
Root web application context loaded by ContextLoaderListener
.
Config location of this context is applicationContext.xml
by default and can be configured using <context-param>
named contextConfigLocation
, i.e. at the top level of web.xml
. This context usually contains a core application logic.
Servlet-specifc context loaded by DispatcherServlet
. Its config location is by default <servletname>-servlet.xml
and can be configured using <init-param>
named contextConfigLocation
, i.e. at servlet level. This context usually contains a Spring MVC-related stuff (controllers, etc) since DispatcherServlet
is a part of Spring MVC.
The latter context is a child of the former.
If web application doesn't use Spring MVC as a presentation framework, it doesn't have DispatcherServlet
and its context. Some extremely simple Spring MVC samples doesn't have ContextLoaderListener
and the root context (however, you need root context for cross-servlet functionality such as Spring Security).
Config files of web application are by default located in webapp's root folder. However, they can be placed in the classpath (i.e. in src/main/webapp
), in this case they are accessed via classpath:
prefix. This may be useful if you are going to use some of these files in integration tests without servlet container. Also classpath:
prefix may be useful when you want to load a config file from a separate artifact, i.e. from a jar file in /WEB-INF/lib
.
I think it is often good style to keep the code, its spring configuration an in a separate JAR that is included into the WAR, such that the WAR is basically empty but for web.xml and the like. This saves you from even asking this question. :-) You can reference those spring configurations with classpath: prefix.
One advantage of this layout is that you can easily write Unittests that instantiate the complete Spring configuration of the WAR within the JAR. I would not necessarily recommend to use this for actual tests (although you can do integration tests this way), but you get a quick feedback when you accidentially break the overall structure of the config files without having to redeploy the application.
If you really need to put spring configuration files into the WAR (perhaps since it also references beans that are implemented in the WAR itself) I would also put them into the normal resources path /WEB-INF/classes, for the reasons discussed above.