Splitting applicationContext to multiple files

SpringConfiguration

Spring Problem Overview


What is the correct way to split Spring's configuration to multiple xml files?

At the moment I have

  • /WEB-INF/foo-servlet.xml
  • /WEB-INF/foo-service.xml
  • /WEB-INF/foo-persistence.xml

My web.xml has the following:

<servlet>
	<description>Spring MVC Dispatcher Servlet</description>
	<servlet-name>intrafest</servlet-name>
	<servlet-class>
		org.springframework.web.servlet.DispatcherServlet
	</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/foo-*.xml
        </param-value>
	</init-param>
	<load-on-startup>2</load-on-startup>
</servlet>

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
        	/WEB-INF/foo-*.xml
	</param-value>
</context-param>


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

The actual questions:

  • Is this approach correct/best?
  • Do I really need to specify the config locations both in the DispatcherServlet AND the context-param sections?

What do I need to keep in mind to be able to reference beans defined in foo-servlet.xml from foo-service.xml? Does this have something to do with specifying contextConfigLocation in web.xml?

Update 1:

I'm using Spring framework 3.0. It's my understanding that I don't need to do resource importing like this:

 <import resource="foo-services.xml"/> 

Is this a correct assumption?

Spring Solutions


Solution 1 - Spring

I find the following setup the easiest.

Use the default config file loading mechanism of DispatcherServlet:

> The framework will, on initialization > of a DispatcherServlet, look for a > file named [servlet-name]-servlet.xml > in the WEB-INF directory of your web > application and create the beans > defined there (overriding the > definitions of any beans defined with > the same name in the global scope).

In your case, simply create a file intrafest-servlet.xml in the WEB-INF dir and don't need to specify anything specific information in web.xml.

In intrafest-servlet.xml file you can use import to compose your XML configuration.

<beans>
  <bean id="bean1" class="..."/>
  <bean id="bean2" class="..."/>

  <import resource="foo-services.xml"/>
  <import resource="foo-persistence.xml"/>
</beans>

Note that the Spring team actually prefers to load multiple config files when creating the (Web)ApplicationContext. If you still want to do it this way, I think you don't need to specify both context parameters (context-param) and servlet initialization parameters (init-param). One of the two will do. You can also use commas to specify multiple config locations.

Solution 2 - Spring

Mike Nereson has this to say on his blog at:

http://blog.codehangover.com/load-multiple-contexts-into-spring/

> There are a couple of ways to do this. > > 1. web.xml contextConfigLocation > > Your first option is to load them all into your Web application > context via the ContextConfigLocation element. You’re already going > to have your primary applicationContext here, assuming you’re writing > a web application. All you need to do is put some white space between > the declaration of the next context. > > > contextConfigLocation > > applicationContext1.xml > applicationContext2.xml > > > > > > org.springframework.web.context.ContextLoaderListener > > > > The above uses carriage returns. Alternatively, yo could just put in a > space. > > > contextConfigLocation > applicationContext1.xml applicationContext2.xml > > > > org.springframework.web.context.ContextLoaderListener > > > 2. applicationContext.xml import resource > > Your other option is to just add your primary applicationContext.xml > to the web.xml and then use import statements in that primary context. > > In applicationContext.xml you might have… > > > > > > > > > > > Which strategy should you use? > > 1. I always prefer to load up via web.xml. > > Because , this allows me to keep all contexts isolated from each > other. With tests, we can load just the contexts that we need to run > those tests. This makes development more modular too as components > stay loosely coupled, so that in the future I can extract a package > or vertical layer and move it to its own module. > > 2. If you are loading contexts into a non-web application, I would use the import resource.

Solution 3 - Spring

There are two types of contexts we are dealing with:

1: root context (parent context. Typically include all jdbc(ORM, Hibernate) initialisation and other spring security related configuration)

2: individual servlet context (child context.Typically Dispatcher Servlet Context and initialise all beans related to spring-mvc (controllers , URL Mapping etc)).

Here is an example of web.xml which includes multiple application context file

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>Spring Web Application example</display-name>

    <!-- Configurations for the root application context (parent context) -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/jdbc/spring-jdbc.xml <!-- JDBC related context -->
            /WEB-INF/spring/security/spring-security-context.xml <!-- Spring Security related context -->
        </param-value>
    </context-param>

    <!-- Configurations for the DispatcherServlet application context (child context) -->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring/mvc/spring-mvc-servlet.xml
            </param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/admin/*</url-pattern>
    </servlet-mapping>

</web-app>

Solution 4 - Spring

@eljenso : intrafest-servlet.xml webapplication context xml will be used if the application uses SPRING WEB MVC.

Otherwise the @kosoant configuration is fine.

Simple example if you dont use SPRING WEB MVC, but want to utitlize SPRING IOC :

In web.xml:

<context-param>
        <param-name>contextConfigLocation</param-name>
    	<param-value>classpath:application-context.xml</param-value>
</context-param>

Then, your application-context.xml will contain: <import resource="foo-services.xml"/> these import statements to load various application context files and put into main application-context.xml.

Thanks and hope this helps.

Solution 5 - Spring

I'm the author of modular-spring-contexts.

This is a small utility library to allow a more modular organization of spring contexts than is achieved by using Composing XML-based configuration metadata. modular-spring-contexts works by defining modules, which are basically stand alone application contexts and allowing modules to import beans from other modules, which are exported ín their originating module.

The key points then are

  • control over dependencies between modules
  • control over which beans are exported and where they are used
  • reduced possibility of naming collisions of beans

A simple example would look like this:

File moduleDefinitions.xml:

<?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:module="http://www.gitlab.com/SpaceTrucker/modular-spring-contexts"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.gitlab.com/SpaceTrucker/modular-spring-contexts xsd/modular-spring-contexts.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<context:annotation-config />

	<module:module id="serverModule">
		<module:config location="/serverModule.xml" />
	</module:module>

	<module:module id="clientModule">
		<module:config location="/clientModule.xml" />
		<module:requires module="serverModule" />
	</module:module>

</beans>

File serverModule.xml:

<?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:module="http://www.gitlab.com/SpaceTrucker/modular-spring-contexts"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.gitlab.com/SpaceTrucker/modular-spring-contexts xsd/modular-spring-contexts.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<context:annotation-config />
	
	<bean id="serverSingleton" class="java.math.BigDecimal" scope="singleton">
		<constructor-arg index="0" value="123.45" />
		<meta key="exported" value="true"/>
	</bean>

</beans>

File clientModule.xml

<?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:module="http://www.gitlab.com/SpaceTrucker/modular-spring-contexts"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.gitlab.com/SpaceTrucker/modular-spring-contexts xsd/modular-spring-contexts.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<context:annotation-config />
	
	<module:import id="importedSingleton" sourceModule="serverModule" sourceBean="serverSingleton" />

</beans>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkosoantView Question on Stackoverflow
Solution 1 - SpringeljensoView Answer on Stackoverflow
Solution 2 - SpringHuman BeingView Answer on Stackoverflow
Solution 3 - Springuser2815238View Answer on Stackoverflow
Solution 4 - SpringSreeniView Answer on Stackoverflow
Solution 5 - SpringSpaceTruckerView Answer on Stackoverflow