Refactor @EnablePdx annotation-based configuration allowing users to register explicit application domain types.
Explicit (Class) type registration conveniently allows java.*, javax.*, com.gemstone.gemfire.*, org.apache.geode.* and org.springframework.* types to be registered, which are excluded by SDG's MappingPdxSerializer by default. Closes #619.
This commit is contained in:
@@ -25,6 +25,7 @@ import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
|
||||
|
||||
/**
|
||||
* The {@link EnablePdx} annotation marks a Spring {@link Configuration @Configuration} annotated {@link Class}
|
||||
@@ -61,6 +62,18 @@ public @interface EnablePdx {
|
||||
*/
|
||||
boolean ignoreUnreadFields() default PdxConfiguration.DEFAULT_IGNORE_UNREAD_FIELDS;
|
||||
|
||||
/**
|
||||
* When using the Spring Data Geode's (SDG) {@link MappingPdxSerializer} most application domain {@link Class types}
|
||||
* are included for Apache Geode PDX serialization, by default. However, certain {@link Class types} are excluded
|
||||
* by SDG's {@link MappingPdxSerializer}, such as {@literal java.*}, {@literal javax.*}, {@literal com.gemstone.*},
|
||||
* {@literal org.apache.geode.*} and {@literal org.springframework.*} {@link Class types}. This allows the default
|
||||
* behavior to be overridden when and where necessary.
|
||||
*
|
||||
* @return an array of {@link Class types} to be handled by the {@link MappingPdxSerializer}, possibly overriding
|
||||
* the excluded {@link Class types} by default.
|
||||
*/
|
||||
Class<?>[] includeDomainTypes() default {};
|
||||
|
||||
/**
|
||||
* Configures whether the type metadata for PDX objects is persisted to disk.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
@@ -36,6 +38,7 @@ import org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFact
|
||||
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
|
||||
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
|
||||
import org.springframework.data.gemfire.support.NoOpBeanFactoryPostProcessor;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -57,6 +60,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
|
||||
* @see org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor
|
||||
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
|
||||
* @see org.springframework.data.gemfire.mapping.MappingPdxSerializer
|
||||
* @see org.springframework.data.gemfire.support.NoOpBeanFactoryPostProcessor
|
||||
* @since 2.1.0
|
||||
@@ -76,6 +80,8 @@ public class PdxConfiguration extends AbstractAnnotationConfigSupport implements
|
||||
private Boolean persistent;
|
||||
private Boolean readSerialized;
|
||||
|
||||
private Class<?>[] includeDomainTypes = {};
|
||||
|
||||
private String diskStoreName;
|
||||
private String serializerBeanName;
|
||||
|
||||
@@ -106,6 +112,8 @@ public class PdxConfiguration extends AbstractAnnotationConfigSupport implements
|
||||
? enablePdxAttributes.getBoolean("ignoreUnreadFields")
|
||||
: DEFAULT_IGNORE_UNREAD_FIELDS));
|
||||
|
||||
setIncludeDomainTypes(enablePdxAttributes.getClassArray("includeDomainTypes"));
|
||||
|
||||
setPersistent(resolveProperty(pdxProperty("persistent"),
|
||||
enablePdxAttributes.containsKey("persistent")
|
||||
? enablePdxAttributes.getBoolean("persistent")
|
||||
@@ -139,6 +147,14 @@ public class PdxConfiguration extends AbstractAnnotationConfigSupport implements
|
||||
return Boolean.TRUE.equals(this.ignoreUnreadFields);
|
||||
}
|
||||
|
||||
void setIncludeDomainTypes(Class<?>[] includeDomainTypes) {
|
||||
this.includeDomainTypes = includeDomainTypes;
|
||||
}
|
||||
|
||||
protected Class<?>[] getIncludeDomainTypes() {
|
||||
return ArrayUtils.nullSafeArray(this.includeDomainTypes, Class.class);
|
||||
}
|
||||
|
||||
void setPersistent(Boolean persistent) {
|
||||
this.persistent = persistent;
|
||||
}
|
||||
@@ -189,7 +205,7 @@ public class PdxConfiguration extends AbstractAnnotationConfigSupport implements
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see <a href="https://geode.apache.org/docs/guide/113/developing/data_serialization/gemfire_pdx_serialization.html">Geode PDX Serialization</a>
|
||||
*/
|
||||
protected void configurePdx(CacheFactoryBean cacheFactoryBean) {
|
||||
protected void configurePdx(@NonNull CacheFactoryBean cacheFactoryBean) {
|
||||
|
||||
getDiskStoreName().ifPresent(cacheFactoryBean::setPdxDiskStoreName);
|
||||
|
||||
@@ -240,15 +256,20 @@ public class PdxConfiguration extends AbstractAnnotationConfigSupport implements
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see #getBeanFactory()
|
||||
*/
|
||||
@NonNull
|
||||
protected PdxSerializer resolvePdxSerializer() {
|
||||
protected @NonNull PdxSerializer resolvePdxSerializer() {
|
||||
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
|
||||
return getSerializerBeanName()
|
||||
PdxSerializer serializer = getSerializerBeanName()
|
||||
.filter(beanFactory::containsBean)
|
||||
.map(beanName -> beanFactory.getBean(beanName, PdxSerializer.class))
|
||||
.orElseGet(this::newPdxSerializer);
|
||||
|
||||
if (serializer instanceof MappingPdxSerializer mappingSerializer) {
|
||||
mappingSerializer.setIncludeTypeFilters(buildIncludeTypeFilters());
|
||||
}
|
||||
|
||||
return serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,11 +279,23 @@ public class PdxConfiguration extends AbstractAnnotationConfigSupport implements
|
||||
* @return a new instance of {@link PdxSerializer}.
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
*/
|
||||
@NonNull
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends PdxSerializer> T newPdxSerializer() {
|
||||
protected @NonNull <T extends PdxSerializer> T newPdxSerializer() {
|
||||
|
||||
return (T) MappingPdxSerializer.create(resolveMappingContext().orElse(null),
|
||||
resolveConversionService().orElse(null));
|
||||
}
|
||||
|
||||
private @NonNull Predicate<Class<?>> buildIncludeTypeFilters() {
|
||||
|
||||
Predicate<Class<?>> includeTypeFilter = type -> false;
|
||||
|
||||
for (Class<?> domainType : getIncludeDomainTypes()) {
|
||||
if (Objects.nonNull(domainType)) {
|
||||
includeTypeFilter = includeTypeFilter.or(type -> domainType.isAssignableFrom(type));
|
||||
}
|
||||
}
|
||||
|
||||
return includeTypeFilter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.gemstone.gemfire.TestGemStoneGemFireType;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Spy;
|
||||
@@ -92,6 +94,7 @@ public class EnablePdxConfigurationUnitTests {
|
||||
|
||||
annotationAttributes.put("diskStoreName", "MockDiskStore");
|
||||
annotationAttributes.put("ignoreUnreadFields", Boolean.TRUE);
|
||||
annotationAttributes.put("includeDomainTypes", new Class[] { TestGemStoneGemFireType.class });
|
||||
annotationAttributes.put("persistent", Boolean.TRUE);
|
||||
annotationAttributes.put("readSerialized", Boolean.TRUE);
|
||||
annotationAttributes.put("serializerBeanName", "MockPdxSerializer");
|
||||
@@ -106,6 +109,7 @@ public class EnablePdxConfigurationUnitTests {
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.getDiskStoreName().orElse(null)).isEqualTo("MockDiskStore");
|
||||
assertThat(this.pdxConfiguration.isIgnoreUnreadFields()).isTrue();
|
||||
assertThat(this.pdxConfiguration.getIncludeDomainTypes()).containsExactly(TestGemStoneGemFireType.class);
|
||||
assertThat(this.pdxConfiguration.isPersistent()).isTrue();
|
||||
assertThat(this.pdxConfiguration.isReadSerialized()).isTrue();
|
||||
assertThat(this.pdxConfiguration.getSerializerBeanName().orElse(null)).isEqualTo("MockPdxSerializer");
|
||||
@@ -126,6 +130,7 @@ public class EnablePdxConfigurationUnitTests {
|
||||
|
||||
assertThat(this.pdxConfiguration.getDiskStoreName().isPresent()).isFalse();
|
||||
assertThat(this.pdxConfiguration.isIgnoreUnreadFields()).isFalse();
|
||||
assertThat(this.pdxConfiguration.getIncludeDomainTypes()).isEmpty();
|
||||
assertThat(this.pdxConfiguration.isPersistent()).isFalse();
|
||||
assertThat(this.pdxConfiguration.isReadSerialized()).isFalse();
|
||||
assertThat(this.pdxConfiguration.getSerializerBeanName().isPresent()).isFalse();
|
||||
@@ -168,6 +173,7 @@ public class EnablePdxConfigurationUnitTests {
|
||||
|
||||
verify(this.pdxConfiguration, times(1)).getDiskStoreName();
|
||||
verify(this.pdxConfiguration, times(1)).isIgnoreUnreadFields();
|
||||
verify(this.pdxConfiguration, never()).getIncludeDomainTypes();
|
||||
verify(this.pdxConfiguration, times(1)).isPersistent();
|
||||
verify(this.pdxConfiguration, times(1)).isReadSerialized();
|
||||
verify(this.pdxConfiguration, times(1)).getSerializerBeanName();
|
||||
|
||||
Reference in New Issue
Block a user