Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document @EntityScan changed in upgrade guide #6340

Closed
hho opened this issue Jul 6, 2016 · 5 comments
Closed

Document @EntityScan changed in upgrade guide #6340

hho opened this issue Jul 6, 2016 · 5 comments
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@hho
Copy link
Contributor

hho commented Jul 6, 2016

Hi,

I'm trying out the new 1.4.0.RC1. In my app, I have two different EntityManagerFactories configured and use Spring Data JPA Repositories.

When I switch from the now deprecated annotation org.springframework.boot.orm.jpa.EntityScan to the new one org.springframework.boot.autoconfigure.domain.EntityScan, my app no longer starts. According to the exception message, the persistence unit is no longer found.

I made a stripped down demo to reproduce the problem: https://github.com/hho/entityscanproblem (mvn test to see it fail)

Stacktrace of the error

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'systemEntityManagerFactory' defined in com.example.infra.SystemHibernateConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No persistence unit with name 'system' found
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076) ~[spring-context-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:851) ~[spring-context-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) ~[spring-context-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-1.4.0.RC1.jar:1.4.0.RC1]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369) ~[spring-boot-1.4.0.RC1.jar:1.4.0.RC1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:313) ~[spring-boot-1.4.0.RC1.jar:1.4.0.RC1]
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:111) [spring-boot-test-1.4.0.RC1.jar:1.4.0.RC1]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.boot.test.autoconfigure.AutoConfigureReportTestExecutionListener.prepareTestInstance(AutoConfigureReportTestExecutionListener.java:46) [spring-boot-test-autoconfigure-1.4.0.RC1.jar:1.4.0.RC1]
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) [spring-test-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) [surefire-junit4-2.18.1.jar:2.18.1]
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) [surefire-junit4-2.18.1.jar:2.18.1]
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) [surefire-junit4-2.18.1.jar:2.18.1]
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) [surefire-junit4-2.18.1.jar:2.18.1]
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) [surefire-booter-2.18.1.jar:2.18.1]
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) [surefire-booter-2.18.1.jar:2.18.1]
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) [surefire-booter-2.18.1.jar:2.18.1]
Caused by: java.lang.IllegalArgumentException: No persistence unit with name 'system' found
    at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.obtainPersistenceUnitInfo(DefaultPersistenceUnitManager.java:697) ~[spring-orm-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.determinePersistenceUnitInfo(LocalContainerEntityManagerFactoryBean.java:357) ~[spring-orm-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:314) ~[spring-orm-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373) ~[spring-orm-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362) ~[spring-orm-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    ... 42 common frames omitted
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 6, 2016
@snicoll snicoll added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 6, 2016
@snicoll snicoll added this to the 1.4.0 milestone Jul 6, 2016
@snicoll snicoll self-assigned this Jul 7, 2016
@snicoll
Copy link
Member

snicoll commented Jul 7, 2016

EntityScanBeanPostProcessor has completely disappeared with the new annotation. JpaBaseConfiguration#getPackagesToScan() was meant to setup the default if the post-processor doesn't kick in and now it's actually fetching the packages to use.

The regression comes from the fact that any custom LocalContainerEntityManagerFactoryBean aren't post-processed anymore. We should restore that.

@snicoll snicoll changed the title org.springframework.boot.autoconfigure.domain.EntityScan causes problems with EntityManagerFactories EntityScan does not post-processe LocalContainerEntityManagerFactoryBean anymore Jul 7, 2016
@snicoll snicoll changed the title EntityScan does not post-processe LocalContainerEntityManagerFactoryBean anymore EntityScan does not post-process LocalContainerEntityManagerFactoryBean anymore Jul 7, 2016
@wilkinsona
Copy link
Member

I'm not 100% convinced that we should. Perhaps someone has created their own LocalContainerEntityManagerFactoryBean because they want to scan a custom set of packages. How would they do that if we always set the packages?

@snicoll
Copy link
Member

snicoll commented Jul 7, 2016

I agree. What I thought to be a regression is actually a more consistent behaviour of boot. If you decide to create your own configuration, Boot should basically back-off and let you do your thing. I wasn't sure about the lifecycle of the post-processor so I created a test and this actually override any customization applied in the @Bean method.

So I think it's more a matter of playing nice with this use case. We can decide to let the user grab the packages manually via EntityScanPackages#get but that's 1.4 only and it requires the bean factory. Another option would be to improve EntityManagerFactoryBuilder#dataSource(DataSource dataSource) so that the default packages are automatically set. That way if no customizations are applied we get the same behaviour and overriding that will override it as expected. Unfortunately, EntityManagerFactoryBuilder is in spring-boot and has no access to the new EntityScanPackages class.

@philwebb
Copy link
Member

philwebb commented Jul 7, 2016

The original @EntityScan was quite confusing in my opinion since it blindly applied itself to all LocalContainerEntityManagerFactoryBean's. I think the preferred option here is to suggest that EntityManagerFactoryBuilder.packages() is called directly.

I.e. Drop @EntityScan from TenantRepositoryConfigurationNew and update SystemHibernateConfiguration & TenantHibernateConfiguration to call builder.packages(PersistentTenant.class).

@snicoll snicoll added type: documentation A documentation update and removed type: regression A regression from a previous release labels Jul 7, 2016
@philwebb philwebb assigned philwebb and unassigned snicoll Jul 7, 2016
@philwebb philwebb changed the title EntityScan does not post-process LocalContainerEntityManagerFactoryBean anymore Document @EntityScan changed in upgrade guide Jul 7, 2016
@philwebb
Copy link
Member

philwebb commented Jul 7, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

5 participants