Skip to content

Commit 4b1ac8a

Browse files
committed
Ensure unique bean definitions for EntityManager beans.
We now make sure to create unique beans to avoid autowiring resolution problems for EntityManager beans through SharedEntityManagerCreator definitions. Closes #2699
1 parent c5e53d5 commit 4b1ac8a

File tree

3 files changed

+52
-24
lines changed

3 files changed

+52
-24
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import org.springframework.beans.factory.config.BeanDefinition;
3939
import org.springframework.beans.factory.support.AbstractBeanDefinition;
4040
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
41-
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
4241
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
4342
import org.springframework.beans.factory.support.RootBeanDefinition;
4443
import org.springframework.context.annotation.AnnotationConfigUtils;
@@ -164,7 +163,7 @@ public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConf
164163

165164
super.registerBeansForRoot(registry, config);
166165

167-
prepareAndRegisterSharedEntityManger(registry, config);
166+
registerSharedEntityMangerIfNotAlreadyRegistered(registry, config);
168167

169168
Object source = config.getSource();
170169

@@ -208,18 +207,24 @@ public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConf
208207
}, registry, JpaEvaluationContextExtension.class.getName(), source);
209208
}
210209

211-
private String prepareAndRegisterSharedEntityManger(BeanDefinitionRegistry registry,
210+
private String registerSharedEntityMangerIfNotAlreadyRegistered(BeanDefinitionRegistry registry,
212211
RepositoryConfigurationSource config) {
213212

214-
AbstractBeanDefinition entityManager = getEntityManagerBeanDefinitionFor(config, null);
215-
entityManager.setRole(BeanDefinition.ROLE_SUPPORT);
216-
entityManager.setSynthetic(true);
217-
entityManager.setPrimary(false);
218-
entityManager.setAutowireCandidate(false);
213+
String entityManagerBeanRef = getEntityManagerBeanRef(config);
214+
String entityManagerBeanName = "jpaSharedEM_" + entityManagerBeanRef;
215+
216+
if (!registry.containsBeanDefinition(entityManagerBeanName)) {
217+
218+
AbstractBeanDefinition entityManager = getEntityManagerBeanDefinitionFor(config, null);
219+
entityManager.setRole(BeanDefinition.ROLE_SUPPORT);
220+
entityManager.setSynthetic(true);
221+
entityManager.setPrimary(false);
222+
entityManager.setAutowireCandidate(false);
223+
224+
registry.registerBeanDefinition(entityManagerBeanName, entityManager);
225+
}
219226

220-
String entityManagerBeanName = BeanDefinitionReaderUtils.uniqueBeanName("jpaSharedEM", registry);
221227
entityManagerRefs.put(config, entityManagerBeanName);
222-
registry.registerBeanDefinition(entityManagerBeanName, entityManager);
223228
return entityManagerBeanName;
224229
}
225230

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/EntityManagerBeanDefinitionRegistrarPostProcessor.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@
2929
import org.springframework.beans.factory.support.AbstractBeanDefinition;
3030
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
3131
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
32-
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
3332
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3433
import org.springframework.core.Ordered;
35-
import org.springframework.data.jpa.util.BeanDefinitionUtils.*;
3634
import org.springframework.orm.jpa.SharedEntityManagerCreator;
3735

3836
/**
@@ -44,6 +42,7 @@
4442
*
4543
* @author Oliver Gierke
4644
* @author Réda Housni Alaoui
45+
* @author Mark Paluch
4746
*/
4847
public class EntityManagerBeanDefinitionRegistrarPostProcessor implements BeanFactoryPostProcessor, Ordered {
4948

@@ -59,7 +58,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
5958
return;
6059
}
6160

62-
ConfigurableListableBeanFactory factory = (ConfigurableListableBeanFactory) beanFactory;
61+
ConfigurableListableBeanFactory factory = beanFactory;
6362

6463
for (EntityManagerFactoryBeanDefinition definition : getEntityManagerFactoryBeanDefinitions(factory)) {
6564

@@ -69,22 +68,27 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
6968
continue;
7069
}
7170

71+
String entityManagerBeanName = "jpaSharedEM_AWC_" + definition.getBeanName();
7272
BeanDefinitionRegistry definitionRegistry = (BeanDefinitionRegistry) definitionFactory;
7373

74-
BeanDefinitionBuilder builder = BeanDefinitionBuilder
75-
.rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator");
76-
builder.setFactoryMethod("createSharedEntityManager");
77-
builder.addConstructorArgReference(definition.getBeanName());
74+
if (!beanFactory.containsBeanDefinition(entityManagerBeanName)
75+
&& !definitionRegistry.containsBeanDefinition(entityManagerBeanName)) {
7876

79-
AbstractBeanDefinition emBeanDefinition = builder.getRawBeanDefinition();
77+
BeanDefinitionBuilder builder = BeanDefinitionBuilder
78+
.rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator");
79+
builder.setFactoryMethod("createSharedEntityManager");
80+
builder.addConstructorArgReference(definition.getBeanName());
8081

81-
emBeanDefinition.setPrimary(definition.getBeanDefinition().isPrimary());
82-
emBeanDefinition.addQualifier(new AutowireCandidateQualifier(Qualifier.class, definition.getBeanName()));
83-
emBeanDefinition.setScope(definition.getBeanDefinition().getScope());
84-
emBeanDefinition.setSource(definition.getBeanDefinition().getSource());
85-
emBeanDefinition.setLazyInit(true);
82+
AbstractBeanDefinition emBeanDefinition = builder.getRawBeanDefinition();
8683

87-
BeanDefinitionReaderUtils.registerWithGeneratedName(emBeanDefinition, definitionRegistry);
84+
emBeanDefinition.setPrimary(definition.getBeanDefinition().isPrimary());
85+
emBeanDefinition.addQualifier(new AutowireCandidateQualifier(Qualifier.class, definition.getBeanName()));
86+
emBeanDefinition.setScope(definition.getBeanDefinition().getScope());
87+
emBeanDefinition.setSource(definition.getBeanDefinition().getSource());
88+
emBeanDefinition.setLazyInit(true);
89+
90+
definitionRegistry.registerBeanDefinition(entityManagerBeanName, emBeanDefinition);
91+
}
8892
}
8993
}
9094
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/EntityManagerBeanDefinitionRegistrarPostProcessorUnitTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
*
3434
* @author Oliver Gierke
3535
* @author Jens Schauder
36+
* @author Mark Paluch
3637
*/
3738
public class EntityManagerBeanDefinitionRegistrarPostProcessorUnitTests {
3839

@@ -65,6 +66,24 @@ void discoversFactoryBeanReturningConcreteEntityManagerFactoryType() {
6566
assertThat(beanFactory.getBeanDefinitionCount()).isEqualTo(2);
6667
}
6768

69+
@Test // gh-2699
70+
void avoidsDuplicateBeanRegistrations() {
71+
72+
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(StubEntityManagerFactoryBean.class);
73+
builder.addConstructorArgValue(SpecialEntityManagerFactory.class);
74+
75+
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
76+
beanFactory.registerBeanDefinition("factory", builder.getBeanDefinition());
77+
78+
beanFactory.registerBeanDefinition("jpaSharedEM_AWC_factory",
79+
BeanDefinitionBuilder.rootBeanDefinition(Object.class).getBeanDefinition());
80+
81+
BeanFactoryPostProcessor processor = new EntityManagerBeanDefinitionRegistrarPostProcessor();
82+
processor.postProcessBeanFactory(beanFactory);
83+
84+
assertThat(beanFactory.getBeanDefinitionCount()).isEqualTo(2);
85+
}
86+
6887
interface SpecialEntityManagerFactory extends EntityManagerFactory {}
6988

7089
static class StubEntityManagerFactoryBean extends LocalContainerEntityManagerFactoryBean {

0 commit comments

Comments
 (0)