From eec6cea9adca862b93b91306cc82d00aaa45946f Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 14 Sep 2020 16:12:56 -0700 Subject: [PATCH] DATAGEODE-306 - Fix compilation errors in GemfireTemplate and MappingPdxSerializer. The compilation errors were caused by the downmerge from Neumann/2.3 to Moore/2.2 and API changes in Spring Data Commons and Mockito. --- .../data/gemfire/GemfireTemplate.java | 21 +++++- .../gemfire/mapping/MappingPdxSerializer.java | 16 ++--- .../support/SimpleGemfireRepository.java | 1 - .../data/gemfire/util/RegionUtils.java | 13 ++++ .../MappingPdxSerializerIntegrationTests.java | 1 - .../MappingPdxSerializerUnitTests.java | 14 ++-- .../SimpleGemfireRepositoryUnitTests.java | 65 +++++++++++++++++-- .../gemfire/util/RegionUtilsUnitTests.java | 18 ++++- .../gemfire/util/SpringUtilsUnitTests.java | 6 +- 9 files changed, 126 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/GemfireTemplate.java b/src/main/java/org/springframework/data/gemfire/GemfireTemplate.java index 428eed39..d98d62c4 100644 --- a/src/main/java/org/springframework/data/gemfire/GemfireTemplate.java +++ b/src/main/java/org/springframework/data/gemfire/GemfireTemplate.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire; import java.lang.reflect.InvocationHandler; @@ -23,6 +22,7 @@ import java.lang.reflect.Proxy; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.geode.GemFireCheckedException; import org.apache.geode.GemFireException; @@ -34,11 +34,14 @@ import org.apache.geode.cache.query.Query; import org.apache.geode.cache.query.QueryInvalidException; import org.apache.geode.cache.query.QueryService; import org.apache.geode.cache.query.SelectResults; -import org.apache.geode.internal.cache.LocalRegion; + import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.gemfire.util.RegionUtils; +import org.springframework.data.gemfire.util.SpringUtils; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** @@ -419,7 +422,19 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation } boolean isLocalWithNoServerProxy(Region region) { - return region instanceof LocalRegion && !((LocalRegion) region).hasServerProxy(); + + if (RegionUtils.isLocal(region)) { + + SpringUtils.ValueReturningThrowableOperation hasServerProxyMethod = () -> + Optional.ofNullable(ReflectionUtils.findMethod(region.getClass(), "hasServerProxy")) + .map(method -> ReflectionUtils.invokeMethod(method, region)) + .map(Boolean.FALSE::equals) + .orElse(false); + + return SpringUtils.safeGetValue(hasServerProxyMethod, false); + } + + return false; } boolean requiresPooledQueryService(Region region) { diff --git a/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java b/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java index 30e22d50..806a2539 100644 --- a/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java +++ b/src/main/java/org/springframework/data/gemfire/mapping/MappingPdxSerializer.java @@ -34,6 +34,8 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.data.convert.EntityInstantiator; +import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.gemfire.util.Filter; import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PersistentEntity; @@ -41,8 +43,6 @@ import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PropertyHandler; import org.springframework.data.mapping.model.ConvertingPropertyAccessor; -import org.springframework.data.mapping.model.EntityInstantiator; -import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider; import org.springframework.data.mapping.model.SpELContext; import org.springframework.lang.NonNull; @@ -72,8 +72,8 @@ import org.slf4j.LoggerFactory; * @see org.springframework.data.mapping.PersistentPropertyAccessor * @see org.springframework.data.mapping.PropertyHandler * @see org.springframework.data.mapping.model.ConvertingPropertyAccessor - * @see org.springframework.data.mapping.model.EntityInstantiator - * @see org.springframework.data.mapping.model.EntityInstantiators + * @see org.springframework.data.convert.EntityInstantiator + * @see org.springframework.data.convert.EntityInstantiators * @see org.springframework.data.mapping.model.PersistentEntityParameterValueProvider * @since 1.2.0 */ @@ -323,7 +323,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw * * @param entityInstantiators {@link EntityInstantiator EntityInstantiators} used to create the instances * read by this {@link PdxSerializer}; must not be {@literal null}. - * @see org.springframework.data.mapping.model.EntityInstantiator + * @see org.springframework.data.convert.EntityInstantiator */ public void setEntityInstantiators(@NonNull EntityInstantiators entityInstantiators) { @@ -338,7 +338,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw * * @param gemfireInstantiators mapping of {@link Class types} to {@link EntityInstantiator} objects; * must not be {@literal null}. - * @see org.springframework.data.mapping.model.EntityInstantiator + * @see org.springframework.data.convert.EntityInstantiator * @see java.util.Map */ public void setEntityInstantiators(@NonNull Map, EntityInstantiator> gemfireInstantiators) { @@ -349,7 +349,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw * Returns the configured {@link EntityInstantiators} handling instantiation for GemFire persistent entities. * * @return the configured {@link EntityInstantiators} handling instantiation for GemFire persistent entities. - * @see org.springframework.data.mapping.model.EntityInstantiators + * @see org.springframework.data.convert.EntityInstantiators */ protected EntityInstantiators getEntityInstantiators() { return this.entityInstantiators; @@ -709,7 +709,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw * @param entity {@link PersistentEntity} object used to lookup a custom, registered {@link EntityInstantiator} * for the entity. * @return an {@link EntityInstantiator} for the given {@link PersistentEntity}. - * @see org.springframework.data.mapping.model.EntityInstantiator + * @see org.springframework.data.convert.EntityInstantiator * @see org.springframework.data.mapping.PersistentEntity */ @SuppressWarnings("rawtypes") diff --git a/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java b/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java index 40b58d62..db57557e 100644 --- a/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java +++ b/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.repository.support; import java.util.Collection; diff --git a/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java b/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java index 54a38bba..6853930d 100644 --- a/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java @@ -21,6 +21,7 @@ import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.client.ClientRegionShortcut; +import org.apache.geode.internal.cache.LocalRegion; import org.springframework.data.gemfire.client.ClientRegionShortcutWrapper; import org.springframework.lang.NonNull; @@ -137,6 +138,18 @@ public abstract class RegionUtils extends CacheUtils { .isPresent(); } + /** + * Determines whether the given {@link Region} is a non-distributed, {@literal local} {@link Region}. + * + * @param region {@link Region} to evaluate. + * @return a boolean value indicating whether the given {@link Region} is a non-distributed, + * {@literal local} {@link Region}. + * @see org.apache.geode.cache.Region + */ + public static boolean isLocal(@Nullable Region region) { + return region instanceof LocalRegion; + } + @Nullable public static String toRegionName(@Nullable Region region) { return Optional.ofNullable(region).map(Region::getName).orElse(null); diff --git a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTests.java index afcd2044..add1385d 100644 --- a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerIntegrationTests.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.mapping; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java index df47bdff..8bc2cab8 100644 --- a/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/mapping/MappingPdxSerializerUnitTests.java @@ -28,7 +28,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException; @@ -55,6 +55,8 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.core.type.ClassMetadata; +import org.springframework.data.convert.EntityInstantiator; +import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.domain.Page; import org.springframework.data.gemfire.GemfireTemplate; import org.springframework.data.gemfire.repository.sample.Account; @@ -72,8 +74,6 @@ import org.springframework.data.gemfire.test.support.MapBuilder; import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.model.EntityInstantiator; -import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mapping.model.ParameterValueProvider; /** @@ -483,8 +483,8 @@ public class MappingPdxSerializerUnitTests { verify(this.pdxSerializer, times(1)).getEntityInstantiators(); verify(mockEntityInstantiators, times(1)).getInstantiatorFor(eq(mockEntity)); - verifyNoInteractions(mockEntityInstantiator); - verifyNoInteractions(mockEntity); + verifyZeroInteractions(mockEntityInstantiator); + verifyZeroInteractions(mockEntity); } @Test @@ -503,8 +503,8 @@ public class MappingPdxSerializerUnitTests { verify(this.pdxSerializer, times(1)).getEntityInstantiators(); verify(mockEntityInstantiators, times(1)).getInstantiatorFor(eq(mockEntity)); - verifyNoInteractions(mockEntityInstantiator); - verifyNoInteractions(mockEntity); + verifyZeroInteractions(mockEntityInstantiator); + verifyZeroInteractions(mockEntity); } @Test diff --git a/src/test/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepositoryUnitTests.java b/src/test/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepositoryUnitTests.java index a4756690..949b5e6a 100644 --- a/src/test/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepositoryUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepositoryUnitTests.java @@ -25,8 +25,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.util.ArrayList; @@ -191,7 +191,7 @@ public class SimpleGemfireRepositoryUnitTests { assertThat(repository).isNotNull(); - verifyNoInteractions(template, mockRegion, mockEntityInformation); + verifyZeroInteractions(template, mockRegion, mockEntityInformation); } @Test(expected = IllegalArgumentException.class) @@ -225,7 +225,9 @@ public class SimpleGemfireRepositoryUnitTests { } @Test - public void saveEntityIsCorrect() { + public void saveEntitySuccessfully() { + + Animal cat = newAnimal(1L, "cat"); Region mockRegion = mockRegion(); @@ -274,7 +276,7 @@ public class SimpleGemfireRepositoryUnitTests { assertThat(repository.save(dogWrapper)).isEqualTo(dog); - verify(mockRegion, times(1)).put(eq(dog.getId()), eq(dog)); + verifyZeroInteractions(mockRegion); } @Test @@ -490,7 +492,60 @@ public class SimpleGemfireRepositoryUnitTests { } @Test - public void deleteByIdIsCorrect() { + public void findAllByIdWithNullIterableIsNullSafe() { + + Region mockRegion = mockRegion(); + + SimpleGemfireRepository repository = + new SimpleGemfireRepository(newGemfireTemplate(mockRegion), mockEntityInformation()); + + Iterable animals = repository.findAllById(null); + + assertThat(animals).isNotNull(); + assertThat(animals).isEmpty(); + + verifyZeroInteractions(mockRegion); + } + + @Test + public void findByIdSuccessfully() { + + Animal dog = newAnimal(1L, "dog"); + + Region mockRegion = mockRegion(); + + doAnswer(invocation -> dog.getId().equals(invocation.getArgument(0)) ? dog : null) + .when(mockRegion).get(any(Long.class)); + + SimpleGemfireRepository repository = + new SimpleGemfireRepository<>(newGemfireTemplate(mockRegion), mockEntityInformation()); + + assertThat(repository.findById(1L).orElse(null)).isEqualTo(dog); + assertThat(repository.findById(2L).isPresent()).isFalse(); + assertThat(repository.findById(10L).isPresent()).isFalse(); + + verify(mockRegion, times(1)).get(eq(1L)); + verify(mockRegion, times(1)).get(eq(2L)); + verify(mockRegion, times(1)).get(eq(10L)); + verifyNoMoreInteractions(mockRegion); + } + + @Test + public void findByIdWithNullIdIsNullSafe() { + + Region mockRegion = mockRegion(); + + SimpleGemfireRepository repository = + new SimpleGemfireRepository(newGemfireTemplate(mockRegion), mockEntityInformation()); + + assertThat(repository.findById(null).isPresent()).isFalse(); + + verifyZeroInteractions(mockRegion); + } + + @Test + public void deleteByIdSuccessfully() { + Region mockRegion = mockRegion(); SimpleGemfireRepository repository = diff --git a/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java b/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java index e93f8aa9..7c1f6c43 100644 --- a/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.util; import static org.assertj.core.api.Assertions.assertThat; @@ -28,6 +27,7 @@ import org.junit.Test; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionService; +import org.apache.geode.internal.cache.LocalRegion; /** * Unit tests for {@link RegionUtils}. @@ -164,4 +164,20 @@ public class RegionUtilsUnitTests { verify(mockRegion, times(1)).getRegionService(); } + + @Test + @SuppressWarnings("all") + public void nullRegionIsNotLocal() { + assertThat(RegionUtils.isLocal(null)).isFalse(); + } + + @Test + public void localRegionIsLocal() { + assertThat(RegionUtils.isLocal(mock(LocalRegion.class))).isTrue(); + } + + @Test + public void nonLocalRegionIsNotLocal() { + assertThat(RegionUtils.isLocal(mock(Region.class))).isFalse(); + } } diff --git a/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java b/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java index ba915aec..2fe51a14 100644 --- a/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java @@ -25,8 +25,8 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.springframework.data.gemfire.util.ArrayUtils.asArray; import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException; @@ -51,7 +51,7 @@ import org.springframework.data.gemfire.test.model.Person; import org.springframework.data.gemfire.util.SpringUtils.ValueReturningThrowableOperation; /** - * Unit tests for {@link SpringUtils}. + * Unit Tests for {@link SpringUtils}. * * @author John Blum * @see java.util.function.Function @@ -416,7 +416,7 @@ public class SpringUtilsUnitTests { assertThat(SpringUtils.safeDoOperation(() -> operationValue.set("MOCK"), mockRunnable)).isTrue(); assertThat(operationValue.get()).isEqualTo("MOCK"); - verifyNoInteractions(mockRunnable); + verifyZeroInteractions(mockRunnable); } @Test