From 076b017d18e36af8a3ece470d4bab96bdeaf5d2f Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Fri, 9 May 2014 11:33:02 +0200 Subject: [PATCH] DATAJPA-525 - Guard against null types returned from JPA meta-model. Some JpaProviders (read: Hibernate in combination with Hibernate Envers) sometimes return null values from ManagedType.getJavaType() for embedded types values. We now explicitly check for null values before adding the type to the initial entity set processed by the mapping context. Related pull request: #89. --- .../config/JpaRepositoryConfigExtension.java | 7 ++- ...JpaRepositoryConfigExtensionUnitTests.java | 43 ++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java index ae548de63..38d3b12aa 100644 --- a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java +++ b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java @@ -203,7 +203,12 @@ public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensi Set> entitySources = new HashSet>(managedTypes.size()); for (ManagedType type : managedTypes) { - entitySources.add(type.getJavaType()); + + Class javaType = type.getJavaType(); + + if (javaType != null) { + entitySources.add(javaType); + } } JpaMetamodelMappingContext context = new JpaMetamodelMappingContext(metamodel); 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 4ce662336..d9629523b 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 the original author or authors. + * Copyright 2013-2014 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. @@ -17,8 +17,15 @@ package org.springframework.data.jpa.repository.config; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; import java.util.Arrays; +import java.util.Collections; +import java.util.Set; + +import javax.persistence.EntityManager; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.Metamodel; import org.hamcrest.Matchers; import org.junit.Rule; @@ -32,6 +39,8 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.AnnotationConfigUtils; +import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +import org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtension.JpaMetamodelMappingContextFactoryBean; import org.springframework.data.repository.config.RepositoryConfigurationExtension; import org.springframework.data.repository.config.RepositoryConfigurationSource; import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor; @@ -47,11 +56,9 @@ public class JpaRepositoryConfigExtensionUnitTests { private static final String RIABPP_CLASS_NAME = "org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor"; private static final String PABPP_CLASS_NAME = "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"; - @Mock - RepositoryConfigurationSource configSource; + @Mock RepositoryConfigurationSource configSource; - @Rule - public ExpectedException exception = ExpectedException.none(); + @Rule public ExpectedException exception = ExpectedException.none(); @Test public void registersDefaultBeanPostProcessorsByDefault() { @@ -63,8 +70,8 @@ public class JpaRepositoryConfigExtensionUnitTests { Iterable names = Arrays.asList(factory.getBeanDefinitionNames()); - assertThat(names, Matchers. hasItem(startsWith(PABPP_CLASS_NAME))); - assertThat(names, Matchers. hasItem(startsWith(RIABPP_CLASS_NAME))); + assertThat(names, Matchers. hasItem(Matchers.startsWith(PABPP_CLASS_NAME))); + assertThat(names, Matchers. hasItem(Matchers.startsWith(RIABPP_CLASS_NAME))); } @Test @@ -89,6 +96,28 @@ public class JpaRepositoryConfigExtensionUnitTests { assertOnlyOnePersistenceAnnotationBeanPostProcessorRegistered(factory, beanName); } + /** + * @see DATAJPA-525 + */ + @Test + public void guardsAgainstNullJavaTypesReturnedFromJpaMetamodel() throws Exception { + + EntityManager em = mock(EntityManager.class); + Metamodel metamodel = mock(Metamodel.class); + ManagedType managedType = mock(ManagedType.class); + + Set> managedTypes = Collections.> singleton(managedType); + + when(em.getMetamodel()).thenReturn(metamodel); + when(metamodel.getManagedTypes()).thenReturn(managedTypes); + + JpaMetamodelMappingContextFactoryBean factoryBean = new JpaRepositoryConfigExtension.JpaMetamodelMappingContextFactoryBean(); + factoryBean.setEntityManager(em); + + JpaMetamodelMappingContext context = factoryBean.createInstance(); + context.afterPropertiesSet(); + } + private void assertOnlyOnePersistenceAnnotationBeanPostProcessorRegistered(DefaultListableBeanFactory factory, String expectedBeanName) {