Friday, September 16, 2011

Spring Application Context Configuration

I have been working with spring framework for a long time and early on I used to maintain different context files for testing, I have done that mostly because of the location of context file was /WEB-INF/ and it is not in either Eclipse or Maven compile/run time class path and my tests would barf with a dreaded File Not Found exception. I realized a better location for spring config files that does not involve MVC configuration should be a source folder under java run time. Since I use Maven project structure It dawned on me that I could use src/main/resources that would resolve compile/run time issues for Eclipse, Maven and also the Server.

Location of spring context files
This is the typical configuration in most my java enterprise applications, I use maven project directory structure so the logically the context files go into resource directory. I also dabbled into placing my spring config files src/test/resources but It still required me to maintain two sets of config files. So I finally settled on src/main/resources as my config directory.
  • src/main/resources/spring-config (Service layer)
  • src/main/webapp/WEB-INF/myapp-servelt.xml (I tend to keep MVC config like controller and view resolver under WEB-INF)
Spring Context files
I used to have more context files but since advent of annotations that number is drastically reduced. You can see that I am firmly in the annotation camp when it comes to configuration whether it is spring or hibernate.  I have typically used the following configuration
Context Files Merging
If you would prefer to minimize the number context file in your application during deployment, You can do some thing like this create an applicationContext.xml and import all the context files that are not part of MVC config. I think it is a good idea to keep MVC config separate. I have listing of an example context file with resources being imported


<?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/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
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">


<context:component-scan base-package="prasanna" />
<import resource="classpath:datasource.xml"/>
<import resource="classpath:applicationContextDAO.xml"/>

</beans>


Junit Testing
It makes running tests easy no need to worry about context file being not found. You can create base test that could be extended by all the other tests some thing like this.

@ContextConfiguration(locations={"classpath:spring-config/applicationContext.xml"})
public class BaseSpringConfigTest
{

}

Since spring context files are under resources directory we can always be sure that Junit tests will run with out fail

Context File for Deploying
Now let's look at the point on how do we deploy the context files to a web application. If you look at any of the spring examples you would see that context files are always under /WEB-INF. In this case every thing still remains the same, I just use the ubiquitous classpath suffix to load the context file. Look at the listing for dispatch servlet below in web.xml


<servlet>
<servlet-name>Spring Dispatch Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-config/applicationContext.xml
 /WEB-INF/mvcConfigContext.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>


If you look at the listing, I used classpath suffix config to load applicatonContext.xml but I still have mvc config file under the WEB-INF directory. If you use Spring ContextLoaderListener you still do the same just load them as below

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config/applicationContext.xml</param-value>
</context-param>

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


<servlet>
<servlet-name>Spring Dispatch Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
 /WEB-INF/mvcConfigContext.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>


if you do the above configuration spring as it boot straps the application context treats the context loaded by the listener as the parent of the context loaded by dispatch servlet. I don't want to get to details into it refer to spring documentation or this excellent article.

As a foot note I would say location of config files, It is more to do with being consistent as it helps with on boarding / hand offs as project resources are shifting. 



No comments:

Post a Comment