joeg3
joeg3

Reputation: 185

Unable to import Spring bean definition file using relative path

I am new to Spring and inherited a Spring project that had all the XML configuration in ProjectName/WebContent/WEB-INF/applicationContext.xml. I'm trying to break the configuration into different components so it is easier to substitute things like DataSources and Hibernate configuation when testing.

Here is my file structure:

ProjectName
  ->WebContent
      ->WEB-INF
          ->applicationContext.xml
          ->spring-datasource.xml
          ->spring-hibernate-properties.xml
          ->spring-persistence.xml
  ->test
      ->us.mn.k12... (Java pkgs with JUnit tests)
      ->spring-hsqldb-datasource.xml
      ->spring-test-bean-locations.xml
      ->spring-test-hibernate-properties.xml
  ->src
      ->us.mn.k12... (Java pkgs with production code)

In WEB-INF/applicationContext.xml, I import the following:

<import resource="spring-datasource.xml"/> <!-- Production datasource -->
<import resource="spring-hibernate-properties.xml"/> <!-- Production hibernate properties -->
<import resource="spring-persistence.xml"/> <!--  DAO's, hibernate .hbm.xml mapping files -->

The application works with the above configuration.

My JUnit tests run using DbUnit and an HSQLDB in-memory database. So my JUnit test references spring-test-bean-locations.xml, which has the following:

<import resource="spring-hsqldb-datasource.xml"/> <!-- HSQLDB datasource for test -->
<import resource="../WebContent/WEB-INF/spring-persistence.xml"/>  <!--  Production DAO's, hibernate .hbm.xml mapping files -->
<import resource="spring-test-hibernate-properties.xml"/> <!-- Hibernate properties for test -->

In this way, I can specify test datasource and hibernate properties, but reuse the production mapping file for the DAO's, etc. However, I get an error running my JUnit test. Here is the relevant part of the exception:

Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from relative location [../WebContent/WEB-INF/spring-persistence.xml]
Offending resource: class path resource [spring-test-bean-locations.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [../WebContent/WEB-INF/spring-persistence.xml]; nested exception is java.io.FileNotFoundException: class path resource [../WebContent/WEB-INF/spring-persistence.xml] cannot be opened because it does not exist

Now if I move spring-persistence.xml into /test so that I don't have to use the relative path, and reference it with <import resource="spring-persistence.xml"/>, then the tests run fine. So I think the contents of my XML files are OK, but I'm not properly importing with a relative path.

Is there anything obvious I'm doing wrong with my import of the relative path? And maybe the bigger question is does this look like a reasonable strategy for breaking applicationContext.xml into components to make it easier for testing?

Thanks!

Upvotes: 9

Views: 35621

Answers (2)

PShetty
PShetty

Reputation: 585

Use

 <import resource="file:**/WebContent/WEB-INF/spring-persistence.xml" />

It works in spring 3.2.1.RELEASE. Old versions I am not sure.

Upvotes: 12

Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 298818

The problem is: anything inside WEB-INF is not available to the ClassLoader in a regular project setup (and spring uses the ClassLoader by default to access resources). There are some hacks to work around this (like referencing the contexts using the file: prefix), but those are mostly ugly.

A better practice I'd suggest is to move the context files out of WEB-INF and into a dedicated resource directory (src/main/resources if you have a maven setup). That way they will be available to both the webapp ClassLoader and local unit test ClassLoaders.

Read the resources chapter to further understand the mechanisms involved.

Upvotes: 18

Related Questions