spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.51k stars 38.11k forks source link

Hibernate LocalSessionFactoryBean ignores classpath when loading mapping resources [SPR-3965] #8645

Closed spring-projects-issues closed 12 years ago

spring-projects-issues commented 17 years ago

John Baker opened SPR-3965 and commented

Consider the following:

\ \

<property name="mappingResources">
  <list>
    <value>Admin.hbm.xml</value>
  </list>
</property>  
...

And the following code sample:

ClassPathXmlApplicationContext appCtx = new
    ClassPathXmlApplicationContext(
          new String[] {
                "configuration-context.xml"
          }, false);
appCtx.setClassLoader(classLoader);
appCtx.refresh();

While the configuration-context.xml is loaded from the classLoader provided, the Hibernate mapping file (Admin.hbm.xml) is loaded from the Thread's classloader. This is because of the following code in LocalSessionFactoryBean:

public void setMappingResources(String[] mappingResources) {
    this.mappingLocations = new Resource[mappingResources.length];
    for (int i = 0; i < mappingResources.length; i++) {
        this.mappingLocations[i] = new ClassPathResource(mappingResources[i].trim());
    }
}

The ClassPathResource is not given a reference to 'classLoader', set on the ClassPathXmlApplicationContext object.

I've discovered this by looking at the classLoader reference in the following section of code (from ClassPathResource):

public InputStream getInputStream() throws IOException {
    InputStream is = null;
    if (this.clazz != null) {
        is = this.clazz.getResourceAsStream(this.path);
    }
    else {
        is = this.classLoader.getResourceAsStream(this.path);
    }
    if (is == null) {
        throw new FileNotFoundException(
                getDescription() + " cannot be opened because it does not exist");
    }
    return is;
}

The classLoader reference is not the one I set here:

appCtx.setClassLoader(classLoader);

Affects: 2.0.5

spring-projects-issues commented 17 years ago

John Baker commented

Here's my first attempt at a fix, which isn't very nice but seems to work.

import org.springframework.context.*; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource;

/**

}

spring-projects-issues commented 17 years ago

Juergen Hoeller commented

Thanks for spotting this! Indeed, we need to use the correct ClassLoader there, else usage in OSGi environments won't work either.

Juergen

spring-projects-issues commented 17 years ago

Juergen Hoeller commented

BTW, as a workaround: Specifying those mapping paths as "mappingLocations", using a "classpath:" prefix in front of each location, should use the correct ClassLoader already. It's only "mappingResources" which doesn't work properly there.

Juergen