Search code examples
javaspringhibernatespring-boothibernate-mapping

Spring Boot *.hbm.xml mapping files not loaded in test


The problem is hard to explain, so please have a look at the project: https://github.com/darzz/boot_bug This is the minimal setup, that reproduces the bug.

Description: The application stack is Spring Boot with Spring Data and Spring Batch. There is testNamedQuery.hbm.xml file under src/main/resources/queries.

When running from Application class the batch job finishes successfully, no exceptions in logs. However, when running from ApplicationNotWorking class, which is exact copy, just put in test source root, the batch job fails:

Caused by: org.hibernate.MappingException: Named query not known: findPersonNames
    at org.hibernate.internal.AbstractSessionImpl.getNamedQuery(AbstractSessionImpl.java:177) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.springframework.batch.item.database.HibernateItemReaderHelper.createQuery(HibernateItemReaderHelper.java:146) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.batch.item.database.HibernateItemReaderHelper.getForwardOnlyCursor(HibernateItemReaderHelper.java:123) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.batch.item.database.HibernateCursorItemReader.doOpen(HibernateCursorItemReader.java:185) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    ... 39 common frames omitted

So it looks like that when running tests, *.hbm.xml files are not loaded! After research and debugging, I think, I might have found the cause - persistence unit root url is set for tests to target/test-classes, but the mapping files are in /target/classes.

Possible cause in my opinion may be similar to what's described in here http://blog.carbonfive.com/2007/05/17/using-classpath-vs-classpath-when-loading-spring-resources/

But I have no idea, how to solve this issue in Spring Boot, without creating persistence.xml configuration just for testing purposes. Don't want to copy *.hbm.xml files from main/resources to test/resources either.

Does anyone have an idea?


Solution

  • @Autowired
    private ResourceLoader rl;
    
    
    @Bean
    public LocalSessionFactoryBean sessionFactory() throws IOException {
        LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
        sessionFactoryBean.setMappingLocations(loadResources());
        return sessionFactoryBean;
    }
    
    public Resource[] loadResources() {
        Resource[] resources = null;
        try {
            resources = ResourcePatternUtils.getResourcePatternResolver(rl)
                .getResources("classpath:/hibernate/*.hbm.xml");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return resources;
    }