Skip to content

Commit dded79d

Browse files
committed
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 spring-projects#619.
1 parent 2f54e7a commit dded79d

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

Diff for: spring-data-geode/src/main/java/org/springframework/data/gemfire/config/annotation/EnablePdx.java

+13
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import org.springframework.context.annotation.Configuration;
2727
import org.springframework.context.annotation.Import;
28+
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
2829

2930
/**
3031
* The {@link EnablePdx} annotation marks a Spring {@link Configuration @Configuration} annotated {@link Class}
@@ -61,6 +62,18 @@
6162
*/
6263
boolean ignoreUnreadFields() default PdxConfiguration.DEFAULT_IGNORE_UNREAD_FIELDS;
6364

65+
/**
66+
* When using the Spring Data Geode's (SDG) {@link MappingPdxSerializer} most application domain {@link Class types}
67+
* are included for Apache Geode PDX serialization, by default. However, certain {@link Class types} are excluded
68+
* by SDG's {@link MappingPdxSerializer}, such as {@literal java.*}, {@literal javax.*}, {@literal com.gemstone.*},
69+
* {@literal org.apache.geode.*} and {@literal org.springframework.*} {@link Class types}. This allows the default
70+
* behavior to be overridden when and where necessary.
71+
*
72+
* @return an array of {@link Class types} to be handled by the {@link MappingPdxSerializer}, possibly overriding
73+
* the excluded {@link Class types} by default.
74+
*/
75+
Class<?>[] includeDomainTypes() default {};
76+
6477
/**
6578
* Configures whether the type metadata for PDX objects is persisted to disk.
6679
*

Diff for: spring-data-geode/src/main/java/org/springframework/data/gemfire/config/annotation/PdxConfiguration.java

+39-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
package org.springframework.data.gemfire.config.annotation;
1717

1818
import java.lang.annotation.Annotation;
19+
import java.util.Objects;
1920
import java.util.Optional;
21+
import java.util.function.Predicate;
2022

2123
import org.apache.geode.cache.GemFireCache;
2224
import org.apache.geode.pdx.PdxSerializer;
@@ -36,6 +38,7 @@
3638
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
3739
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
3840
import org.springframework.data.gemfire.support.NoOpBeanFactoryPostProcessor;
41+
import org.springframework.data.gemfire.util.ArrayUtils;
3942
import org.springframework.lang.NonNull;
4043
import org.springframework.util.StringUtils;
4144

@@ -57,6 +60,7 @@
5760
* @see org.springframework.data.gemfire.CacheFactoryBean
5861
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
5962
* @see org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor
63+
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
6064
* @see org.springframework.data.gemfire.mapping.MappingPdxSerializer
6165
* @see org.springframework.data.gemfire.support.NoOpBeanFactoryPostProcessor
6266
* @since 2.1.0
@@ -76,6 +80,8 @@ public class PdxConfiguration extends AbstractAnnotationConfigSupport implements
7680
private Boolean persistent;
7781
private Boolean readSerialized;
7882

83+
private Class<?>[] includeDomainTypes = {};
84+
7985
private String diskStoreName;
8086
private String serializerBeanName;
8187

@@ -106,6 +112,8 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {
106112
? enablePdxAttributes.getBoolean("ignoreUnreadFields")
107113
: DEFAULT_IGNORE_UNREAD_FIELDS));
108114

115+
setIncludeDomainTypes(enablePdxAttributes.getClassArray("includeDomainTypes"));
116+
109117
setPersistent(resolveProperty(pdxProperty("persistent"),
110118
enablePdxAttributes.containsKey("persistent")
111119
? enablePdxAttributes.getBoolean("persistent")
@@ -139,6 +147,14 @@ protected boolean isIgnoreUnreadFields() {
139147
return Boolean.TRUE.equals(this.ignoreUnreadFields);
140148
}
141149

150+
void setIncludeDomainTypes(Class<?>[] includeDomainTypes) {
151+
this.includeDomainTypes = includeDomainTypes;
152+
}
153+
154+
protected Class<?>[] getIncludeDomainTypes() {
155+
return ArrayUtils.nullSafeArray(this.includeDomainTypes, Class.class);
156+
}
157+
142158
void setPersistent(Boolean persistent) {
143159
this.persistent = persistent;
144160
}
@@ -189,7 +205,7 @@ PeerCacheConfigurer peerCachePdxConfigurer() {
189205
* @see org.springframework.data.gemfire.CacheFactoryBean
190206
* @see <a href="https://geode.apache.org/docs/guide/113/developing/data_serialization/gemfire_pdx_serialization.html">Geode PDX Serialization</a>
191207
*/
192-
protected void configurePdx(CacheFactoryBean cacheFactoryBean) {
208+
protected void configurePdx(@NonNull CacheFactoryBean cacheFactoryBean) {
193209

194210
getDiskStoreName().ifPresent(cacheFactoryBean::setPdxDiskStoreName);
195211

@@ -240,15 +256,20 @@ protected Optional<GemfireMappingContext> resolveMappingContext() {
240256
* @see org.apache.geode.pdx.PdxSerializer
241257
* @see #getBeanFactory()
242258
*/
243-
@NonNull
244-
protected PdxSerializer resolvePdxSerializer() {
259+
protected @NonNull PdxSerializer resolvePdxSerializer() {
245260

246261
BeanFactory beanFactory = getBeanFactory();
247262

248-
return getSerializerBeanName()
263+
PdxSerializer serializer = getSerializerBeanName()
249264
.filter(beanFactory::containsBean)
250265
.map(beanName -> beanFactory.getBean(beanName, PdxSerializer.class))
251266
.orElseGet(this::newPdxSerializer);
267+
268+
if (serializer instanceof MappingPdxSerializer mappingSerializer) {
269+
mappingSerializer.setIncludeTypeFilters(buildIncludeTypeFilters());
270+
}
271+
272+
return serializer;
252273
}
253274

254275
/**
@@ -258,11 +279,23 @@ protected PdxSerializer resolvePdxSerializer() {
258279
* @return a new instance of {@link PdxSerializer}.
259280
* @see org.apache.geode.pdx.PdxSerializer
260281
*/
261-
@NonNull
262282
@SuppressWarnings("unchecked")
263-
protected <T extends PdxSerializer> T newPdxSerializer() {
283+
protected @NonNull <T extends PdxSerializer> T newPdxSerializer() {
264284

265285
return (T) MappingPdxSerializer.create(resolveMappingContext().orElse(null),
266286
resolveConversionService().orElse(null));
267287
}
288+
289+
private @NonNull Predicate<Class<?>> buildIncludeTypeFilters() {
290+
291+
Predicate<Class<?>> includeTypeFilter = type -> false;
292+
293+
for (Class<?> domainType : getIncludeDomainTypes()) {
294+
if (Objects.nonNull(domainType)) {
295+
includeTypeFilter = includeTypeFilter.or(type -> domainType.isAssignableFrom(type));
296+
}
297+
}
298+
299+
return includeTypeFilter;
300+
}
268301
}

Diff for: spring-data-geode/src/test/java/org/springframework/data/gemfire/config/annotation/EnablePdxConfigurationUnitTests.java

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import java.util.Map;
3434
import java.util.Optional;
3535

36+
import com.gemstone.gemfire.TestGemStoneGemFireType;
37+
3638
import org.junit.Test;
3739
import org.junit.runner.RunWith;
3840
import org.mockito.Spy;
@@ -92,6 +94,7 @@ public void setImportMetadataWhenEnablePdxIsConfigured() {
9294

9395
annotationAttributes.put("diskStoreName", "MockDiskStore");
9496
annotationAttributes.put("ignoreUnreadFields", Boolean.TRUE);
97+
annotationAttributes.put("includeDomainTypes", new Class[] { TestGemStoneGemFireType.class });
9598
annotationAttributes.put("persistent", Boolean.TRUE);
9699
annotationAttributes.put("readSerialized", Boolean.TRUE);
97100
annotationAttributes.put("serializerBeanName", "MockPdxSerializer");
@@ -106,6 +109,7 @@ public void setImportMetadataWhenEnablePdxIsConfigured() {
106109
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
107110
assertThat(this.pdxConfiguration.getDiskStoreName().orElse(null)).isEqualTo("MockDiskStore");
108111
assertThat(this.pdxConfiguration.isIgnoreUnreadFields()).isTrue();
112+
assertThat(this.pdxConfiguration.getIncludeDomainTypes()).containsExactly(TestGemStoneGemFireType.class);
109113
assertThat(this.pdxConfiguration.isPersistent()).isTrue();
110114
assertThat(this.pdxConfiguration.isReadSerialized()).isTrue();
111115
assertThat(this.pdxConfiguration.getSerializerBeanName().orElse(null)).isEqualTo("MockPdxSerializer");
@@ -126,6 +130,7 @@ public void setImportMetadataWhenEnablePdxIsNotConfigured() {
126130

127131
assertThat(this.pdxConfiguration.getDiskStoreName().isPresent()).isFalse();
128132
assertThat(this.pdxConfiguration.isIgnoreUnreadFields()).isFalse();
133+
assertThat(this.pdxConfiguration.getIncludeDomainTypes()).isEmpty();
129134
assertThat(this.pdxConfiguration.isPersistent()).isFalse();
130135
assertThat(this.pdxConfiguration.isReadSerialized()).isFalse();
131136
assertThat(this.pdxConfiguration.getSerializerBeanName().isPresent()).isFalse();
@@ -168,6 +173,7 @@ public void configuresPdxForCacheFactoryBean() {
168173

169174
verify(this.pdxConfiguration, times(1)).getDiskStoreName();
170175
verify(this.pdxConfiguration, times(1)).isIgnoreUnreadFields();
176+
verify(this.pdxConfiguration, never()).getIncludeDomainTypes();
171177
verify(this.pdxConfiguration, times(1)).isPersistent();
172178
verify(this.pdxConfiguration, times(1)).isReadSerialized();
173179
verify(this.pdxConfiguration, times(1)).getSerializerBeanName();

0 commit comments

Comments
 (0)