diff --git a/src/main/java/org/springframework/data/jpa/util/BeanDefinitionUtils.java b/src/main/java/org/springframework/data/jpa/util/BeanDefinitionUtils.java index 32be5ba8b..ec76eb833 100644 --- a/src/main/java/org/springframework/data/jpa/util/BeanDefinitionUtils.java +++ b/src/main/java/org/springframework/data/jpa/util/BeanDefinitionUtils.java @@ -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> EMF_TYPES; + + static { + + List> types = new ArrayList>(); + 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 getEntityManagerFactoryBeanDefinitions( ConfigurableListableBeanFactory beanFactory) { List definitions = new ArrayList(); - 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 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); } } } diff --git a/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java index 646f9f6de..f0e6cb44a 100644 --- a/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java @@ -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 names = Arrays.asList(factory.getBeanDefinitionNames()); - assertThat(names, Matchers. hasItem(AnnotationConfigUtils.PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); - assertThat(names, Matchers. hasItem(RIABPP_CLASS_NAME)); + assertThat(names, hasItems(AnnotationConfigUtils.PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME, RIABPP_CLASS_NAME)); } @Test diff --git a/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java index eab7a8a00..e1b8da124 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java @@ -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) { diff --git a/src/test/resources/config/jpa-context-with-jndi.xml b/src/test/resources/config/jpa-context-with-jndi.xml new file mode 100644 index 000000000..70be5f779 --- /dev/null +++ b/src/test/resources/config/jpa-context-with-jndi.xml @@ -0,0 +1,20 @@ + + + + + + + + + +