DATAGEODE-352 - EnableEntityDefinedRegions.includeFilters are inappropriately overridden by framework provided include filters.

This commit is contained in:
John Blum
2020-06-19 17:57:00 -07:00
parent 4d5b661bdd
commit 95455cd542
8 changed files with 135 additions and 80 deletions

View File

@@ -14,7 +14,6 @@
* limitations under the License.
*
*/
package org.springframework.data.gemfire.config.annotation;
import java.lang.annotation.Documented;

View File

@@ -68,6 +68,7 @@ import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.gemfire.mapping.annotation.LocalRegion;
import org.springframework.data.gemfire.mapping.annotation.PartitionRegion;
import org.springframework.data.gemfire.mapping.annotation.ReplicateRegion;
import org.springframework.data.gemfire.support.CompositeTypeFilter;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -172,10 +173,16 @@ public class EntityDefinedRegionsConfiguration extends AbstractAnnotationConfigS
Set<String> resolvedBasePackages =
resolveBasePackages(importingClassMetadata, enableEntityDefinedRegionsAttributes);
TypeFilter resolvedIncludesTypeFilter =
CompositeTypeFilter.composeOr(resolveIncludes(enableEntityDefinedRegionsAttributes));
TypeFilter resolvedRegionAnnotatedPersistentEntityTypeFilter =
CompositeTypeFilter.composeOr(resolveRegionAnnotatedPersistentEntityTypeFilters());
return GemFireComponentClassTypeScanner.from(resolvedBasePackages).with(resolveBeanClassLoader())
.withExcludes(resolveExcludes(enableEntityDefinedRegionsAttributes))
.withIncludes(resolveIncludes(enableEntityDefinedRegionsAttributes))
.withIncludes(resolveRegionAnnotatedPersistentEntityTypeFilters());
.withIncludes(CompositeTypeFilter.composeAnd(resolvedIncludesTypeFilter,
resolvedRegionAnnotatedPersistentEntityTypeFilter));
}
protected Set<String> resolveBasePackages(AnnotationMetadata importingClassMetaData,
@@ -208,7 +215,6 @@ public class EntityDefinedRegionsConfiguration extends AbstractAnnotationConfigS
return parseFilters(enableEntityDefinedRegionsAttributes.getAnnotationArray("includeFilters"));
}
@SuppressWarnings("unchecked")
protected Iterable<TypeFilter> resolveRegionAnnotatedPersistentEntityTypeFilters() {
return org.springframework.data.gemfire.mapping.annotation.Region.REGION_ANNOTATION_TYPES.stream()
@@ -632,7 +638,7 @@ public class EntityDefinedRegionsConfiguration extends AbstractAnnotationConfigS
return resolvePersistentEntity().getRegionAnnotation();
}
@SuppressWarnings("unchecked")
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Class<?> getRegionKeyConstraint() {
return Optional.ofNullable(resolvePersistentEntity().getIdProperty())

View File

@@ -14,7 +14,6 @@
* limitations under the License.
*
*/
package org.springframework.data.gemfire.config.annotation.support;
import static java.util.stream.StreamSupport.stream;
@@ -30,9 +29,6 @@ import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.env.Environment;
@@ -42,6 +38,9 @@ import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link GemFireComponentClassTypeScanner} class is a classpath component scanner used to search
* for Pivotal GemFire components based on {@link Class} type.

View File

@@ -14,7 +14,6 @@
* limitations under the License.
*
*/
package org.springframework.data.gemfire.mapping.annotation;
import java.lang.annotation.Annotation;
@@ -43,7 +42,6 @@ import org.springframework.core.annotation.AliasFor;
@SuppressWarnings("unused")
public @interface Region {
@SuppressWarnings("unchecked")
List<Class<? extends Annotation>> REGION_ANNOTATION_TYPES =
Arrays.asList(ClientRegion.class, LocalRegion.class, PartitionRegion.class, ReplicateRegion.class, Region.class);

View File

@@ -13,19 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.config.annotation;
package org.springframework.data.gemfire.config;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Optional;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Region;
import org.junit.After;
import org.junit.Test;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Region;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.MutablePropertySources;
@@ -36,12 +35,11 @@ import org.springframework.data.gemfire.test.model.Person;
import org.springframework.mock.env.MockPropertySource;
/**
* Integration tests for {@link EnableEntityDefinedRegions} and {@link EntityDefinedRegionsConfiguration}.
* Integration Tests for {@link EnableEntityDefinedRegions} and {@link EntityDefinedRegionsConfiguration}.
*
* @author John Blum
* @see org.junit.Test
* @see org.apache.geode.cache.Region
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions
* @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration
* @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects
@@ -95,6 +93,6 @@ public class EnableEntityDefinedRegionsIntegrationTests {
@ClientCacheApplication
@EnableGemFireMockObjects
@EnableEntityDefinedRegions
static class TestConfiguration {
}
static class TestConfiguration { }
}

View File

@@ -14,8 +14,7 @@
* limitations under the License.
*
*/
package org.springframework.data.gemfire.config.annotation;
package org.springframework.data.gemfire.config;
import static java.util.Arrays.stream;
import static org.assertj.core.api.Assertions.assertThat;
@@ -28,6 +27,9 @@ import static org.springframework.data.gemfire.util.RegionUtils.toRegionPath;
import java.util.List;
import java.util.Optional;
import org.junit.After;
import org.junit.Test;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.FixedPartitionAttributes;
@@ -42,9 +44,6 @@ import org.apache.geode.cache.Scope;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.client.Pool;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -69,16 +68,13 @@ import org.springframework.data.gemfire.test.mock.MockObjectsSupport;
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
/**
* Unit tests for the {@link EnableEntityDefinedRegions} annotation and {@link EntityDefinedRegionsConfiguration} class.
* Unit Tests for the {@link EnableEntityDefinedRegions} annotation and {@link EntityDefinedRegionsConfiguration} class.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.Region
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
* @see org.springframework.context.annotation.Bean
* @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions
* @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration
* @see org.springframework.data.gemfire.mapping.annotation.ClientRegion
@@ -90,6 +86,7 @@ import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockOb
* @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects
* @since 1.9.0
*/
@SuppressWarnings({ "unchecked", "unused" })
public class EnableEntityDefinedRegionsUnitTests {
private ConfigurableApplicationContext applicationContext;
@@ -99,25 +96,20 @@ public class EnableEntityDefinedRegionsUnitTests {
Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close);
}
/* (non-Javadoc) */
protected <K, V> void assertRegion(Region<K, V> region, String name) {
assertRegion(region, name, toRegionPath(name), null, null);
}
/* (non-Javadoc) */
protected <K, V> void assertRegion(Region<K, V> region, String name,
Class<K> keyConstraint, Class<V> valueConstraint) {
assertRegion(region, name, toRegionPath(name), keyConstraint, valueConstraint);
}
/* (non-Javadoc) */
@SuppressWarnings("unused")
protected <K, V> void assertRegion(Region<K, V> region, String name, String fullPath) {
assertRegion(region, name, fullPath, null, null);
}
/* (non-Javadoc) */
protected <K, V> void assertRegion(Region<K, V> region, String name, String fullPath,
Class<K> keyConstraint, Class<V> valueConstraint) {
@@ -129,7 +121,6 @@ public class EnableEntityDefinedRegionsUnitTests {
assertThat(region.getAttributes().getValueConstraint()).isEqualTo(valueConstraint);
}
/* (non-Javadoc) */
protected <K, V> void assertRegionWithAttributes(Region<K, V> region, String name, DataPolicy dataPolicy,
String diskStoreName, Boolean diskSynchronous, Boolean ignoreJta, String poolName, Scope scope) {
@@ -139,7 +130,6 @@ public class EnableEntityDefinedRegionsUnitTests {
poolName, scope);
}
/* (non-Javadoc) */
protected <K, V> void assertRegionAttributes(RegionAttributes<K, V> regionAttributes, DataPolicy dataPolicy,
String diskStoreName, Boolean diskSynchronous, Boolean ignoreJta, String poolName, Scope scope) {
@@ -152,9 +142,8 @@ public class EnableEntityDefinedRegionsUnitTests {
assertThat(regionAttributes.getScope()).isEqualTo(scope);
}
/* (non-Javadoc) */
protected <K, V> void assertPartitionAttributes(PartitionAttributes<K, V> partitionAttributes,
String collocatedWith, PartitionResolver partitionResolver, Integer redundantCopies) {
String collocatedWith, PartitionResolver<?, ?> partitionResolver, Integer redundantCopies) {
assertThat(partitionAttributes).isNotNull();
assertThat(partitionAttributes.getColocatedWith()).isEqualTo(collocatedWith);
@@ -162,7 +151,6 @@ public class EnableEntityDefinedRegionsUnitTests {
assertThat(partitionAttributes.getRedundantCopies()).isEqualTo(redundantCopies);
}
/* (non-Javadoc) */
protected void assertFixedPartitionAttributes(FixedPartitionAttributes fixedPartitionAttributes,
String partitionName, boolean primary, int numBuckets) {
@@ -180,9 +168,7 @@ public class EnableEntityDefinedRegionsUnitTests {
assertThat(this.applicationContext.getBeansOfType(Region.class)).hasSize(11 - length(regionBeanNames));
}
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
protected FixedPartitionAttributes findFixedPartitionAttributes(PartitionAttributes partitionAttributes,
protected FixedPartitionAttributes findFixedPartitionAttributes(PartitionAttributes<?, ?> partitionAttributes,
String partitionName) {
assertThat(partitionAttributes).isNotNull();
@@ -199,7 +185,6 @@ public class EnableEntityDefinedRegionsUnitTests {
return null;
}
/* (non-Javadoc) */
protected ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(annotatedClasses);
applicationContext.registerShutdownHook();
@@ -207,7 +192,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityClientRegionsDefined() {
this.applicationContext = newApplicationContext(ClientPersistentEntitiesConfiguration.class);
@@ -231,7 +215,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityClientRegionsDefinedWithCustomConfiguration() {
this.applicationContext = newApplicationContext(ClientPersistentEntitiesWithCustomConfiguration.class);
@@ -253,7 +236,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityClientRegionsDefinedWithServerRegionMappingAnnotations() {
this.applicationContext =
@@ -298,7 +280,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityPeerPartitionRegionsDefined() {
this.applicationContext = newApplicationContext(PeerPartitionRegionPersistentEntitiesConfiguration.class);
@@ -342,7 +323,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityReplicateRegionAlreadyDefinedIgnoresEntityDefinedRegionDefinition() {
this.applicationContext = newApplicationContext(ExistingReplicateRegionPersistentEntitiesConfiguration.class);
@@ -354,7 +334,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityServerRegionsDefined() {
this.applicationContext = newApplicationContext(ServerPersistentEntitiesConfiguration.class);
@@ -387,7 +366,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityServerRegionsDefinedWithCustomConfiguration() {
this.applicationContext = newApplicationContext(ServerPersistentEntitiesWithCustomConfiguration.class);
@@ -419,7 +397,6 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Test
@SuppressWarnings("unchecked")
public void entityServerRegionsDefinedWithClientRegionMappingAnnotations() {
this.applicationContext =
@@ -454,12 +431,10 @@ public class EnableEntityDefinedRegionsUnitTests {
LocalRegion.class, PartitionRegion.class, ReplicateRegion.class
})
)
static class ClientPersistentEntitiesConfiguration {
}
static class ClientPersistentEntitiesConfiguration { }
@ClientCacheApplication
@EnableGemFireMockObjects
@SuppressWarnings("unused")
@EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, clientRegionShortcut = ClientRegionShortcut.LOCAL,
poolName = "TestPool", excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = { LocalRegion.class, PartitionRegion.class, ReplicateRegion.class })
@@ -478,12 +453,10 @@ public class EnableEntityDefinedRegionsUnitTests {
strict = true, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = CollocatedPartitionRegionEntity.class)
)
static class ClientPersistentEntitiesWithServerRegionMappingAnnotationsConfiguration {
}
static class ClientPersistentEntitiesWithServerRegionMappingAnnotationsConfiguration { }
@PeerCacheApplication
@EnableGemFireMockObjects
@SuppressWarnings("unused")
@EnableEntityDefinedRegions(basePackageClasses = NonEntity.class, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {
ClientRegion.class, LocalRegion.class, ReplicateRegion.class
@@ -498,7 +471,7 @@ public class EnableEntityDefinedRegionsUnitTests {
}
@Bean @Lazy
PartitionResolver mockPartitionResolver() {
PartitionResolver<?, ?> mockPartitionResolver() {
return mock(PartitionResolver.class,
MockObjectsSupport.mockObjectIdentifier("MockPartitionResolver"));
}
@@ -510,8 +483,7 @@ public class EnableEntityDefinedRegionsUnitTests {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = ClientRegion.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = CollocatedPartitionRegionEntity.class)
})
static class ServerPersistentEntitiesConfiguration {
}
static class ServerPersistentEntitiesConfiguration { }
@PeerCacheApplication
@EnableGemFireMockObjects
@@ -520,8 +492,7 @@ public class EnableEntityDefinedRegionsUnitTests {
CollocatedPartitionRegionEntity.class, ReplicateRegionEntity.class
})
)
static class ServerPersistentEntitiesWithCustomConfiguration {
}
static class ServerPersistentEntitiesWithCustomConfiguration { }
@PeerCacheApplication
@EnableGemFireMockObjects
@@ -530,8 +501,7 @@ public class EnableEntityDefinedRegionsUnitTests {
CollocatedPartitionRegionEntity.class, LocalRegionEntity.class, ReplicateRegionEntity.class
})
)
static class ServerPersistentEntitiesWithClientRegionMappingAnnotationsConfiguration {
}
static class ServerPersistentEntitiesWithClientRegionMappingAnnotationsConfiguration { }
@PeerCacheApplication
@EnableGemFireMockObjects
@@ -544,7 +514,6 @@ public class EnableEntityDefinedRegionsUnitTests {
static class ExistingPartitionRegionPersistentEntitiesConfiguration {
@Bean
@SuppressWarnings("unused")
PartitionedRegionFactoryBean<Long, PartitionRegionEntity> customersRegion(GemFireCache gemfireCache) {
PartitionedRegionFactoryBean<Long, PartitionRegionEntity> customers = new PartitionedRegionFactoryBean<>();
@@ -569,7 +538,6 @@ public class EnableEntityDefinedRegionsUnitTests {
static class ExistingReplicateRegionPersistentEntitiesConfiguration {
@Bean
@SuppressWarnings("unused")
ReplicatedRegionFactoryBean<Long, ReplicateRegionEntity> accountsRegion(GemFireCache gemfireCache) {
ReplicatedRegionFactoryBean<Long, ReplicateRegionEntity> accounts = new ReplicatedRegionFactoryBean<>();

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.config.annotation;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.gemfire.repository.sample.Algorithm;
import org.springframework.data.gemfire.repository.sample.User;
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Integration Tests for {@link EnableEntityDefinedRegions} and {@link EntityDefinedRegionsConfiguration}.
*
* @author John Blum
* @see org.junit.Test
* @see org.apache.geode.cache.Region
* @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions
* @see org.springframework.data.gemfire.config.annotation.EntityDefinedRegionsConfiguration
* @since 2.4.0
*/
@RunWith(SpringRunner.class)
@ContextConfiguration
@SuppressWarnings("unused")
public class EnableEntityDefinedRegionsWithAssignableTypeFilterIntegrationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
public void onlyRegionsMatchedByFilterExist() {
Set<String> regionBeanNames = Optional.ofNullable(this.applicationContext.getBeansOfType(Region.class))
.map(Map::values)
.orElseGet(Collections::emptySet)
.stream()
.filter(Objects::nonNull)
.map(Region::getFullPath)
.collect(Collectors.toSet());
assertThat(regionBeanNames).isNotNull();
assertThat(regionBeanNames).hasSize(4);
assertThat(regionBeanNames)
.containsExactlyInAnyOrder("/Users", "/Programmers", "/Local/Admin/Users", "/Local/Guest/Users");
}
@ClientCacheApplication
@EnableGemFireMockObjects
@EnableEntityDefinedRegions(
basePackageClasses = Algorithm.class,
clientRegionShortcut = ClientRegionShortcut.LOCAL,
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "Programmer"),
includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = User.class)
)
static class TestGeodeConfiguration { }
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.repository.sample;
import java.util.Calendar;
@@ -45,11 +44,15 @@ public class User implements Comparable<User> {
@Id
private final String username;
public User(final String username) {
public User(String username) {
Assert.hasText(username, "The username is required!");
this.username = username;
}
public void setActive(final Boolean active) {
this.active = Boolean.TRUE.equals(active);
}
public Boolean getActive() {
return active;
}
@@ -58,26 +61,22 @@ public class User implements Comparable<User> {
return Boolean.TRUE.equals(getActive());
}
public void setActive(final Boolean active) {
this.active = Boolean.TRUE.equals(active);
public void setEmail(final String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setEmail(final String email) {
this.email = email;
public void setSince(final Calendar since) {
this.since = since;
}
public Calendar getSince() {
return since;
}
public void setSince(final Calendar since) {
this.since = since;
}
public String getUsername() {
return username;
}
@@ -87,8 +86,8 @@ public class User implements Comparable<User> {
return getUsername().compareTo(user.getUsername());
}
protected static boolean equalsIgnoreNull(final Object obj1, final Object obj2) {
return (obj1 == null ? obj2 == null : obj1.equals(obj2));
protected static boolean equalsIgnoreNull(Object obj1, Object obj2) {
return obj1 == null ? obj2 == null : obj1.equals(obj2);
}
@Override
@@ -108,8 +107,8 @@ public class User implements Comparable<User> {
&& ObjectUtils.nullSafeEquals(this.getEmail(), that.getEmail());
}
protected static int hashCodeIgnoreNull(final Object obj) {
return (obj != null ? obj.hashCode() : 0);
protected static int hashCodeIgnoreNull(Object obj) {
return obj != null ? obj.hashCode() : 0;
}
@Override