DATAJPA-813 - Improved EntityManagerFactory detection for JndiObjectFactoryBeans.
The lookup of EntityManagerFactory bean definition now also detects JndiObjectFactoryBean instances that have the expected type configured to EntityManagerFactory. Related ticket: DATACMNS-821.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,8 +19,8 @@ import static java.util.Arrays.*;
|
||||
import static org.springframework.beans.factory.BeanFactoryUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -33,7 +33,9 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.jndi.JndiObjectFactoryBean;
|
||||
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Utility methods to work with {@link BeanDefinition} instances from {@link BeanFactoryPostProcessor}s.
|
||||
@@ -42,6 +44,22 @@ import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
|
||||
*/
|
||||
public class BeanDefinitionUtils {
|
||||
|
||||
private static final String JNDI_OBJECT_FACTORY_BEAN = "org.springframework.jndi.JndiObjectFactoryBean";
|
||||
private static final List<Class<?>> EMF_TYPES;
|
||||
|
||||
static {
|
||||
|
||||
List<Class<?>> types = new ArrayList<Class<?>>();
|
||||
types.add(EntityManagerFactory.class);
|
||||
types.add(AbstractEntityManagerFactoryBean.class);
|
||||
|
||||
if (ClassUtils.isPresent(JNDI_OBJECT_FACTORY_BEAN, ClassUtils.getDefaultClassLoader())) {
|
||||
types.add(JndiObjectFactoryBean.class);
|
||||
}
|
||||
|
||||
EMF_TYPES = Collections.unmodifiableList(types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all bean names for bean definitions that will result in an {@link EntityManagerFactory} eventually. We're
|
||||
* checking for {@link EntityManagerFactory} and the well-known factory beans here to avoid eager initialization of
|
||||
@@ -71,24 +89,15 @@ public class BeanDefinitionUtils {
|
||||
* @param beanFactory must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Collection<EntityManagerFactoryBeanDefinition> getEntityManagerFactoryBeanDefinitions(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
List<EntityManagerFactoryBeanDefinition> definitions = new ArrayList<EntityManagerFactoryBeanDefinition>();
|
||||
|
||||
for (Class<?> type : Arrays.asList(EntityManagerFactory.class, AbstractEntityManagerFactoryBean.class)) {
|
||||
for (Class<?> type : EMF_TYPES) {
|
||||
|
||||
for (String name : beanFactory.getBeanNamesForType(type, true, false)) {
|
||||
|
||||
String transformedName = transformedBeanName(name);
|
||||
|
||||
EntityManagerFactoryBeanDefinition definition = new EntityManagerFactoryBeanDefinition( //
|
||||
transformedName, //
|
||||
beanFactory, //
|
||||
beanFactory.getBeanDefinition(transformedName));
|
||||
|
||||
definitions.add(definition);
|
||||
registerEntityManagerFactoryBeanDefinition(transformedBeanName(name), beanFactory, definitions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +110,28 @@ public class BeanDefinitionUtils {
|
||||
return definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an {@link EntityManagerFactoryBeanDefinition} for the bean with the given name. Drops
|
||||
* {@link JndiObjectFactoryBean} instances that don't point to an {@link EntityManagerFactory} bean as expected type.
|
||||
*
|
||||
* @param name
|
||||
* @param beanFactory
|
||||
* @param definitions
|
||||
*/
|
||||
private static void registerEntityManagerFactoryBeanDefinition(String name,
|
||||
ConfigurableListableBeanFactory beanFactory, List<EntityManagerFactoryBeanDefinition> definitions) {
|
||||
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(name);
|
||||
|
||||
if (JNDI_OBJECT_FACTORY_BEAN.equals(definition.getBeanClassName())) {
|
||||
if (!definition.getPropertyValues().get("expectedType").equals(EntityManagerFactory.class.getName())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
definitions.add(new EntityManagerFactoryBeanDefinition(name, beanFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link BeanDefinition} with the given name, obtained from the given {@link BeanFactory} or one of its
|
||||
* parents.
|
||||
@@ -134,21 +165,18 @@ public class BeanDefinitionUtils {
|
||||
public static class EntityManagerFactoryBeanDefinition {
|
||||
|
||||
private final String beanName;
|
||||
private final BeanFactory beanFactory;
|
||||
private final BeanDefinition beanDefinition;
|
||||
private final ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
/**
|
||||
* Creates a new {@link EntityManagerFactoryBeanDefinition}.
|
||||
*
|
||||
* @param beanName
|
||||
* @param beanFactory
|
||||
* @param beanDefinition
|
||||
*/
|
||||
public EntityManagerFactoryBeanDefinition(String beanName, BeanFactory beanFactory, BeanDefinition beanDefinition) {
|
||||
public EntityManagerFactoryBeanDefinition(String beanName, ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
this.beanName = beanName;
|
||||
this.beanFactory = beanFactory;
|
||||
this.beanDefinition = beanDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,7 +203,7 @@ public class BeanDefinitionUtils {
|
||||
* @return
|
||||
*/
|
||||
public BeanDefinition getBeanDefinition() {
|
||||
return beanDefinition;
|
||||
return beanFactory.getBeanDefinition(beanName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
@@ -42,6 +41,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationSource;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
|
||||
|
||||
/**
|
||||
@@ -52,11 +52,11 @@ import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcesso
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaRepositoryConfigExtensionUnitTests {
|
||||
|
||||
private static final String RIABPP_CLASS_NAME = "org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor";
|
||||
private static final String RIABPP_CLASS_NAME = RepositoryFactoryBeanSupport.class.getName().concat("_Predictor");
|
||||
|
||||
@Mock RepositoryConfigurationSource configSource;
|
||||
|
||||
@Rule public ExpectedException exception = ExpectedException.none();
|
||||
public @Rule ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void registersDefaultBeanPostProcessorsByDefault() {
|
||||
@@ -68,8 +68,7 @@ public class JpaRepositoryConfigExtensionUnitTests {
|
||||
|
||||
Iterable<String> names = Arrays.asList(factory.getBeanDefinitionNames());
|
||||
|
||||
assertThat(names, Matchers.<String> hasItem(AnnotationConfigUtils.PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertThat(names, Matchers.<String> hasItem(RIABPP_CLASS_NAME));
|
||||
assertThat(names, hasItems(AnnotationConfigUtils.PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME, RIABPP_CLASS_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -37,12 +37,14 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.jpa.domain.sample.Category;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.JpaContext;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -123,6 +125,23 @@ public class DefaultJpaContextIntegrationTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-813
|
||||
*/
|
||||
@Test
|
||||
public void bootstrapsDefaultJpaContextInSpringContainerWithEntityManagerFromJndi() throws Exception {
|
||||
|
||||
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
|
||||
builder.bind("some/EMF", createEntityManagerFactory("spring-data-jpa"));
|
||||
|
||||
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("config/jpa-context-with-jndi.xml");
|
||||
ApplicationComponent component = context.getBean(ApplicationComponent.class);
|
||||
|
||||
assertThat(component.context, is(notNullValue()));
|
||||
|
||||
context.close();
|
||||
}
|
||||
|
||||
private static final LocalContainerEntityManagerFactoryBean createEntityManagerFactoryBean(
|
||||
String persistenceUnitName) {
|
||||
|
||||
|
||||
20
src/test/resources/config/jpa-context-with-jndi.xml
Normal file
20
src/test/resources/config/jpa-context-with-jndi.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
|
||||
xmlns:jee="http://www.springframework.org/schema/jee"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
|
||||
|
||||
<jpa:repositories base-package="org.springframework.data.jpa.repository.support" />
|
||||
|
||||
<jee:jndi-lookup id="entityManagerFactory"
|
||||
jndi-name="some/EMF"
|
||||
expected-type="javax.persistence.EntityManagerFactory" />
|
||||
|
||||
<bean class="org.springframework.data.jpa.repository.support.DefaultJpaContextIntegrationTests$ApplicationComponent" autowire="constructor" />
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user