SGF-757 - Move configuration of PDX to a PdxConfiguration class imported by the EnablePdx annotation.

This commit is contained in:
John Blum
2018-06-09 17:38:10 -07:00
parent af3671a495
commit da7305a916
11 changed files with 908 additions and 405 deletions

View File

@@ -33,17 +33,12 @@ import org.apache.geode.cache.TransactionWriter;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.cache.util.GatewayConflictResolver;
import org.apache.geode.pdx.PdxSerializer;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.CacheFactoryBean;
@@ -51,9 +46,6 @@ import org.springframework.data.gemfire.config.annotation.support.AbstractAnnota
import org.springframework.data.gemfire.config.support.CustomEditorBeanFactoryPostProcessor;
import org.springframework.data.gemfire.config.support.DefinedIndexesApplicationListener;
import org.springframework.data.gemfire.config.support.DiskStoreDirectoryBeanPostProcessor;
import org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
import org.springframework.data.gemfire.util.PropertiesBuilder;
import org.springframework.util.StringUtils;
@@ -72,7 +64,6 @@ import org.springframework.util.StringUtils;
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.server.CacheServer
* @see org.apache.geode.pdx.PdxSerializer
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.config.BeanDefinition
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder
@@ -80,7 +71,7 @@ import org.springframework.util.StringUtils;
* @see org.springframework.context.annotation.Bean
* @see org.springframework.context.annotation.Configuration
* @see org.springframework.context.annotation.ImportAware
* @see org.springframework.core.convert.ConversionService
* @see org.springframework.core.annotation.AnnotationAttributes
* @see org.springframework.core.io.Resource
* @see org.springframework.core.type.AnnotationMetadata
* @see org.springframework.data.gemfire.CacheFactoryBean
@@ -89,19 +80,20 @@ import org.springframework.util.StringUtils;
* @see org.springframework.data.gemfire.config.support.CustomEditorBeanFactoryPostProcessor
* @see org.springframework.data.gemfire.config.support.DefinedIndexesApplicationListener
* @see org.springframework.data.gemfire.config.support.DiskStoreDirectoryBeanPostProcessor
* @see org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
* @see org.springframework.data.gemfire.mapping.MappingPdxSerializer
* @since 1.9.0
*/
@Configuration
@SuppressWarnings("unused")
public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
private static final AtomicBoolean CUSTOM_EDITORS_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean CUSTOM_EDITORS_BEAN_FACTORY_POST_PROCESSOR_REGISTERED =
new AtomicBoolean(false);
private static final AtomicBoolean DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED =
new AtomicBoolean(false);
private static final AtomicBoolean DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED =
new AtomicBoolean(false);
protected static final boolean DEFAULT_CLOSE = true;
protected static final boolean DEFAULT_COPY_ON_READ = false;
@@ -117,13 +109,9 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
private boolean copyOnRead = DEFAULT_COPY_ON_READ;
private boolean useBeanFactoryLocator = DEFAULT_USE_BEAN_FACTORY_LOCATOR;
private Boolean pdxIgnoreUnreadFields;
private Boolean pdxPersistent;
private Boolean pdxReadSerialized;
private DynamicRegionSupport dynamicRegionSupport;
private Integer mcastPort = 0;
private Integer mcastPort = DEFAULT_MCAST_PORT;
private Float criticalHeapPercentage;
private Float criticalOffHeapPercentage;
@@ -132,14 +120,9 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
private GatewayConflictResolver gatewayConflictResolver;
@Autowired(required = false)
private GemfireMappingContext mappingContext;
private List<JndiDataSource> jndiDataSources;
private List<TransactionListener> transactionListeners;
private PdxSerializer pdxSerializer;
private PropertiesBuilder customGemFireProperties = PropertiesBuilder.create();
private Resource cacheXml;
@@ -147,7 +130,6 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
private String locators = DEFAULT_LOCATORS;
private String logLevel = DEFAULT_LOG_LEVEL;
private String name;
private String pdxDiskStoreName;
private String startLocator;
private TransactionWriter transactionWriter;
@@ -197,8 +179,7 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
configureInfrastructure(importMetadata);
configureCache(importMetadata);
configurePdx(importMetadata);
configureTheRest(importMetadata);
configureOptional(importMetadata);
}
/**
@@ -216,16 +197,14 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
registerDiskStoreDirectoryBeanPostProcessor(importMetadata);
}
/* (non-Javadoc) */
private void registerCustomEditorBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
if (CUSTOM_EDITORS_REGISTERED.compareAndSet(false, true)) {
if (CUSTOM_EDITORS_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
register(BeanDefinitionBuilder.rootBeanDefinition(CustomEditorBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
}
}
/* (non-Javadoc) */
private void registerDefinedIndexesApplicationListener(AnnotationMetadata importMetadata) {
if (DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED.compareAndSet(false, true)) {
@@ -234,7 +213,6 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
}
}
/* (non-Javadoc) */
private void registerDiskStoreDirectoryBeanPostProcessor(AnnotationMetadata importMetadata) {
if (DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
@@ -303,117 +281,14 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
}
/**
* Configures Pivotal GemFire/Apache Geode cache PDX Serialization.
*
* @param importMetadata {@link AnnotationMetadata} containing PDX meta-data used to configure the cache
* with PDX de/serialization capabilities.
* @see org.springframework.core.type.AnnotationMetadata
* @see <a href="http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/data_serialization/gemfire_pdx_serialization.html">Pivotal GemFire PDX Serialization</a>
*/
protected void configurePdx(AnnotationMetadata importMetadata) {
String enablePdxTypeName = EnablePdx.class.getName();
if (importMetadata.hasAnnotation(enablePdxTypeName)) {
AnnotationAttributes enablePdxAttributes = getAnnotationAttributes(importMetadata, enablePdxTypeName);
setPdxDiskStoreName(resolveProperty(pdxProperty("disk-store-name"),
(String) enablePdxAttributes.get("diskStoreName")));
setPdxIgnoreUnreadFields(resolveProperty(pdxProperty("ignore-unread-fields"),
Boolean.TRUE.equals(enablePdxAttributes.get("ignoreUnreadFields"))));
setPdxPersistent(resolveProperty(pdxProperty("persistent"),
Boolean.TRUE.equals(enablePdxAttributes.get("persistent"))));
setPdxReadSerialized(resolveProperty(pdxProperty("read-serialized"),
Boolean.TRUE.equals(enablePdxAttributes.get("readSerialized"))));
setPdxSerializer(resolvePdxSerializer((String) enablePdxAttributes.get("serializerBeanName")));
registerPdxDiskStoreAwareBeanFactoryPostProcessor(importMetadata);
}
}
/**
* Resolves the {@link PdxSerializer} used to configure the cache for PDX De/Serialization.
*
* @param pdxSerializerBeanName {@link String} containing the name of a Spring bean
* implementing the {@link PdxSerializer} interface.
* @return the resolved {@link PdxSerializer} from configuration.
* @see org.apache.geode.pdx.PdxSerializer
* @see #newPdxSerializer(BeanFactory)
* @see #getBeanFactory()
*/
protected PdxSerializer resolvePdxSerializer(String pdxSerializerBeanName) {
BeanFactory beanFactory = getBeanFactory();
return Optional.ofNullable(pdxSerializerBeanName)
.filter(beanFactory::containsBean)
.map(beanName -> beanFactory.getBean(beanName, PdxSerializer.class))
.orElseGet(() -> Optional.ofNullable(getPdxSerializer()).orElseGet(() -> newPdxSerializer(beanFactory)));
}
/**
* Constructs a new instance of {@link PdxSerializer}.
*
* @param <T> {@link Class} type of the {@link PdxSerializer}.
* @return a new instance of {@link PdxSerializer}.
* @see org.apache.geode.pdx.PdxSerializer
* @see #newPdxSerializer(BeanFactory)
*/
@SuppressWarnings("unchecked")
protected <T extends PdxSerializer> T newPdxSerializer() {
return newPdxSerializer(getBeanFactory());
}
/**
* Constructs a new instance of {@link MappingPdxSerializer}.
*
* @param <T> {@link Class} type of the {@link PdxSerializer}; this method returns a {@link MappingPdxSerializer}.
* @param beanFactory {@link BeanFactory} used to get an instance of {@link ConversionService}
* used by the {@link MappingPdxSerializer}.
* @return a new instance of {@link MappingPdxSerializer}.
* @see org.springframework.data.gemfire.mapping.MappingPdxSerializer
* @see org.springframework.beans.factory.BeanFactory
* @see org.apache.geode.pdx.PdxSerializer
*/
@SuppressWarnings("unchecked")
protected <T extends PdxSerializer> T newPdxSerializer(BeanFactory beanFactory) {
Optional<ConversionService> conversionService = Optional.ofNullable(beanFactory)
.filter(it -> it instanceof ConfigurableBeanFactory)
.map(it -> ((ConfigurableBeanFactory) it).getConversionService());
return (T) MappingPdxSerializer.create(this.mappingContext, conversionService.orElse(null));
}
/* (non-Javadoc) */
private void registerPdxDiskStoreAwareBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
Optional.ofNullable(getPdxDiskStoreName())
.filter(StringUtils::hasText)
.ifPresent(pdxDiskStoreName -> {
if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
.addConstructorArgValue(pdxDiskStoreName)
.getBeanDefinition());
}
});
}
/**
=======
>>>>>>> 09d8cc7... DATAGEODE-117 - Move configuration of PDX to a PdxConfiguration class imported by the EnablePdx annotation.
* Callback method allowing developers to configure other cache or application specific configuration settings.
*
* @param importMetadata {@link AnnotationMetadata} containing meta-data used to configure the cache or application.
* @see org.springframework.core.type.AnnotationMetadata
*/
protected void configureTheRest(AnnotationMetadata importMetadata) {
}
protected void configureOptional(AnnotationMetadata importMetadata) { }
/**
* Constructs a new, initialized instance of {@link CacheFactoryBean} based on the Spring application's
@@ -477,11 +352,6 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
gemfireCache.setGatewayConflictResolver(getGatewayConflictResolver());
gemfireCache.setJndiDataSources(getJndiDataSources());
gemfireCache.setProperties(gemfireProperties());
gemfireCache.setPdxDiskStoreName(getPdxDiskStoreName());
gemfireCache.setPdxIgnoreUnreadFields(getPdxIgnoreUnreadFields());
gemfireCache.setPdxPersistent(getPdxPersistent());
gemfireCache.setPdxReadSerialized(getPdxReadSerialized());
gemfireCache.setPdxSerializer(getPdxSerializer());
gemfireCache.setTransactionListeners(getTransactionListeners());
gemfireCache.setTransactionWriter(getTransactionWriter());
@@ -551,7 +421,7 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
protected boolean isTypedCacheApplication(Class<? extends Annotation> annotationType,
AnnotationMetadata importMetadata) {
return (annotationType.equals(getAnnotationType()) && importMetadata.hasAnnotation(getAnnotationTypeName()));
return annotationType.equals(getAnnotationType()) && importMetadata.hasAnnotation(getAnnotationTypeName());
}
/**
@@ -687,14 +557,6 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
return Optional.ofNullable(this.logLevel).orElse(DEFAULT_LOG_LEVEL);
}
void setMappingContext(GemfireMappingContext mappingContext) {
this.mappingContext = mappingContext;
}
protected GemfireMappingContext mappingContext() {
return this.mappingContext;
}
void setMcastPort(Integer mcastPort) {
this.mcastPort = mcastPort;
this.locators = DEFAULT_LOCATORS;
@@ -712,46 +574,6 @@ public abstract class AbstractCacheConfiguration extends AbstractAnnotationConfi
return Optional.ofNullable(this.name).filter(StringUtils::hasText).orElseGet(this::toString);
}
void setPdxDiskStoreName(String pdxDiskStoreName) {
this.pdxDiskStoreName = pdxDiskStoreName;
}
protected String getPdxDiskStoreName() {
return this.pdxDiskStoreName;
}
void setPdxIgnoreUnreadFields(Boolean pdxIgnoreUnreadFields) {
this.pdxIgnoreUnreadFields = pdxIgnoreUnreadFields;
}
protected Boolean getPdxIgnoreUnreadFields() {
return this.pdxIgnoreUnreadFields;
}
void setPdxPersistent(Boolean pdxPersistent) {
this.pdxPersistent = pdxPersistent;
}
protected Boolean getPdxPersistent() {
return this.pdxPersistent;
}
void setPdxReadSerialized(Boolean pdxReadSerialized) {
this.pdxReadSerialized = pdxReadSerialized;
}
protected Boolean getPdxReadSerialized() {
return this.pdxReadSerialized;
}
void setPdxSerializer(PdxSerializer pdxSerializer) {
this.pdxSerializer = pdxSerializer;
}
protected PdxSerializer getPdxSerializer() {
return this.pdxSerializer;
}
void setStartLocator(String startLocator) {
this.startLocator = startLocator;
}

View File

@@ -172,7 +172,7 @@ public class CacheServerConfiguration extends PeerCacheConfiguration {
* @see org.apache.geode.cache.server.CacheServer
*/
@Override
protected void configureTheRest(AnnotationMetadata importMetadata) {
protected void configureOptional(AnnotationMetadata importMetadata) {
super.configureCache(importMetadata);

View File

@@ -154,7 +154,6 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
return gemfireCache;
}
/* (non-Javadoc) */
@SuppressWarnings("all")
private List<ClientCacheConfigurer> resolveClientCacheConfigurers() {

View File

@@ -25,6 +25,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.type.AnnotationMetadata;
/**
@@ -34,13 +35,16 @@ import org.springframework.core.type.AnnotationMetadata;
*
* @author John Blum
* @see java.lang.annotation.Annotation
* @see org.springframework.context.annotation.Import
* @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration#configurePdx(AnnotationMetadata)
* @see org.springframework.data.gemfire.config.annotation.PdxConfiguration
* @since 1.9.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import(PdxConfiguration.class)
@SuppressWarnings("unused")
public @interface EnablePdx {
@@ -49,7 +53,7 @@ public @interface EnablePdx {
*
* Use the {@literal spring.data.gemfire.pdx.disk-store-name} property in {@literal application.properties}.
*/
String diskStoreName() default "";
String diskStoreName() default PdxConfiguration.DEFAULT_PDX_DISK_STORE_NAME;
/**
* Configures whether pdx ignores fields that were unread during deserialization.
@@ -58,7 +62,7 @@ public @interface EnablePdx {
*
* Use the {@literal spring.data.gemfire.pdx.ignore-unread-fields} property in {@literal application.properties}.
*/
boolean ignoreUnreadFields() default false;
boolean ignoreUnreadFields() default PdxConfiguration.DEFAULT_IGNORE_UNREAD_FIELDS;
/**
* Configures whether the type metadata for PDX objects is persisted to disk.
@@ -67,7 +71,7 @@ public @interface EnablePdx {
*
* Use the {@literal spring.data.gemfire.pdx.persistent} property in {@literal application.properties}.
*/
boolean persistent() default false;
boolean persistent() default PdxConfiguration.DEFAULT_PERSISTENT;
/**
* Configures the object preference to {@link org.apache.geode.pdx.PdxInstance} type or {@link Object}.
@@ -76,11 +80,13 @@ public @interface EnablePdx {
*
* Use the {@literal spring.data.gemfire.pdx.read-serialized} property in {@literal application.properties}.
*/
boolean readSerialized() default false;
boolean readSerialized() default PdxConfiguration.DEFAULT_READ_SERIALIZED;
/**
* Configures the PDX serializer to be used by the cache to serialize object data.
*
* Use the {@literal spring.data.gemfire.pdx.serializer-bean-name} property in {@literal application.properties}.
*/
String serializerBeanName() default "";
String serializerBeanName() default PdxConfiguration.DEFAULT_PDX_SERIALIZER_BEAN_NAME;
}

View File

@@ -0,0 +1,269 @@
/*
* Copyright 2018 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
*
* http://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 java.lang.annotation.Annotation;
import java.util.Optional;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.pdx.PdxSerializer;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
import org.springframework.data.gemfire.config.support.PdxDiskStoreAwareBeanFactoryPostProcessor;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
import org.springframework.data.gemfire.support.NoOpBeanFactoryPostProcessor;
import org.springframework.lang.NonNull;
import org.springframework.util.StringUtils;
/**
* The {@link PdxConfiguration} class is a Spring {@link Configuration} class that configures PDX
* on a {@link GemFireCache} instance.
*
* @author John Blum
* @see org.apache.geode.cache.GemFireCache
* @see org.apache.geode.pdx.PdxSerializer
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory
* @see org.springframework.context.annotation.Bean
* @see org.springframework.context.annotation.Configuration
* @see org.springframework.context.annotation.ImportAware
* @see org.springframework.core.annotation.AnnotationAttributes
* @see org.springframework.core.type.AnnotationMetadata
* @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.MappingPdxSerializer
* @see org.springframework.data.gemfire.support.NoOpBeanFactoryPostProcessor
* @since 2.1.0
*/
@SuppressWarnings("unused")
@Configuration("PdxConfiguration")
public class PdxConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
public static final boolean DEFAULT_IGNORE_UNREAD_FIELDS = false;
public static final boolean DEFAULT_PERSISTENT = false;
public static final boolean DEFAULT_READ_SERIALIZED = false;
public static final String DEFAULT_PDX_DISK_STORE_NAME = "";
public static final String DEFAULT_PDX_SERIALIZER_BEAN_NAME = "";
private Boolean ignoreUnreadFields;
private Boolean persistent;
private Boolean readSerialized;
private String diskStoreName;
private String serializerBeanName;
@Override
protected Class<? extends Annotation> getAnnotationType() {
return EnablePdx.class;
}
@Override
protected BeanFactory getBeanFactory() {
return super.getBeanFactory();
}
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
if (isAnnotationPresent(importMetadata)) {
AnnotationAttributes enablePdxAttributes = getAnnotationAttributes(importMetadata);
setDiskStoreName(resolveProperty(pdxProperty("disk-store-name"),
enablePdxAttributes.containsKey("diskStoreName")
? enablePdxAttributes.getString("diskStoreName")
: null));
setIgnoreUnreadFields(resolveProperty(pdxProperty("ignore-unread-fields"),
enablePdxAttributes.containsKey("ignoreUnreadFields")
? enablePdxAttributes.getBoolean("ignoreUnreadFields")
: DEFAULT_IGNORE_UNREAD_FIELDS));
setPersistent(resolveProperty(pdxProperty("persistent"),
enablePdxAttributes.containsKey("persistent")
? enablePdxAttributes.getBoolean("persistent")
: null));
setReadSerialized(resolveProperty(pdxProperty("read-serialized"),
enablePdxAttributes.containsKey("readSerialized")
? enablePdxAttributes.getBoolean("readSerialized")
: null));
setSerializerBeanName(resolveProperty(pdxProperty("serializer-bean-name"),
enablePdxAttributes.containsKey("serializerBeanName")
? enablePdxAttributes.getString("serializerBeanName")
: null));
}
}
void setDiskStoreName(String diskStoreName) {
this.diskStoreName = diskStoreName;
}
protected Optional<String> getDiskStoreName() {
return Optional.ofNullable(this.diskStoreName).filter(StringUtils::hasText);
}
void setIgnoreUnreadFields(Boolean ignoreUnreadFields) {
this.ignoreUnreadFields = ignoreUnreadFields;
}
protected boolean isIgnoreUnreadFields() {
return Boolean.TRUE.equals(this.ignoreUnreadFields);
}
void setPersistent(Boolean persistent) {
this.persistent = persistent;
}
protected boolean isPersistent() {
return Boolean.TRUE.equals(this.persistent);
}
void setReadSerialized(Boolean readSerialized) {
this.readSerialized = readSerialized;
}
protected boolean isReadSerialized() {
return Boolean.TRUE.equals(this.readSerialized);
}
void setSerializerBeanName(String serializerBeanName) {
this.serializerBeanName = serializerBeanName;
}
protected Optional<String> getSerializerBeanName() {
return Optional.ofNullable(this.serializerBeanName).filter(StringUtils::hasText);
}
@Bean
BeanFactoryPostProcessor pdxDiskStoreAwareBeanFactoryPostProcessor() {
return getDiskStoreName()
.<BeanFactoryPostProcessor>map(PdxDiskStoreAwareBeanFactoryPostProcessor::new)
.orElse(NoOpBeanFactoryPostProcessor.INSTANCE);
}
@Bean
ClientCacheConfigurer clientCachePdxConfigurer() {
return (beanName, clientCacheFactoryBean) -> configurePdx(clientCacheFactoryBean);
}
@Bean
PeerCacheConfigurer peerCachePdxConfigurer() {
return (beanName, cacheFactoryBean) -> configurePdx(cacheFactoryBean);
}
/**
* Configures Pivotal GemFire/Apache Geode cache PDX Serialization.
*
* @param cacheFactoryBean {@link CacheFactoryBean} instance on which to configure PDX.
* with PDX de/serialization capabilities.
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see <a href="http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/data_serialization/gemfire_pdx_serialization.html">GemFire PDX Serialization</a>
*/
protected void configurePdx(CacheFactoryBean cacheFactoryBean) {
getDiskStoreName().ifPresent(cacheFactoryBean::setPdxDiskStoreName);
cacheFactoryBean.setPdxIgnoreUnreadFields(isIgnoreUnreadFields());
cacheFactoryBean.setPdxPersistent(isPersistent());
cacheFactoryBean.setPdxReadSerialized(isReadSerialized());
cacheFactoryBean.setPdxSerializer(resolvePdxSerializer());
}
/**
* Resolves the configured {@link ConversionService} from the {@link BeanFactory}.
*
* @return an {@link Optional optionally} configured {@link ConversionService}.
* @see org.springframework.core.convert.ConversionService
* @see java.util.Optional
* @see #getBeanFactory()
*/
protected Optional<ConversionService> resolveConversionService() {
return Optional.of(getBeanFactory())
.filter(it -> it instanceof ConfigurableBeanFactory)
.map(it -> ((ConfigurableBeanFactory) it).getConversionService());
}
/**
* Returns any configured {@link GemfireMappingContext} registered in the {@link BeanFactory}.
*
* @return an {@link Optional optionally} configured {@link GemfireMappingContext}.
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
* @see java.util.Optional
* @see #getBeanFactory()
*/
protected Optional<GemfireMappingContext> resolveMappingContext() {
try {
return Optional.of(getBeanFactory().getBean(GemfireMappingContext.class));
}
catch (Throwable ignore) {
return Optional.empty();
}
}
/**
* Resolves the {@link PdxSerializer} used to configure the cache for PDX Serialization.
*
* implementing the {@link PdxSerializer} interface.
* @return the resolved {@link PdxSerializer} from configuration.
* @see org.apache.geode.pdx.PdxSerializer
* @see #getBeanFactory()
*/
@NonNull
@SuppressWarnings("unchecked")
protected PdxSerializer resolvePdxSerializer() {
BeanFactory beanFactory = getBeanFactory();
return getSerializerBeanName()
.filter(beanFactory::containsBean)
.map(beanName -> beanFactory.getBean(beanName, PdxSerializer.class))
.orElseGet(this::newPdxSerializer);
}
/**
* Constructs a new instance of {@link PdxSerializer}.
*
* @param <T> {@link Class} type of the {@link PdxSerializer}.
* @return a new instance of {@link PdxSerializer}.
* @see org.apache.geode.pdx.PdxSerializer
*/
@NonNull
@SuppressWarnings("unchecked")
protected <T extends PdxSerializer> T newPdxSerializer() {
return (T) MappingPdxSerializer.create(resolveMappingContext().orElse(null),
resolveConversionService().orElse(null));
}
}

View File

@@ -61,7 +61,9 @@ public class PdxDiskStoreAwareBeanFactoryPostProcessor implements BeanFactoryPos
* @throws IllegalArgumentException if the Pivotal GemFire PDX {@link DiskStore} name is unspecified.
*/
public PdxDiskStoreAwareBeanFactoryPostProcessor(String pdxDiskStoreName) {
Assert.hasText(pdxDiskStoreName, "PDX DiskStore name is required");
this.pdxDiskStoreName = pdxDiskStoreName;
}
@@ -104,7 +106,7 @@ public class PdxDiskStoreAwareBeanFactoryPostProcessor implements BeanFactoryPos
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
// NOTE for simplicity sake, we add a bean dependency to any bean definition for a bean
// (Async Event Queue, Region, Disk Store or otherwise) that may potentially require
// (Async Event Queue, Disk Store, Region, or otherwise) that may potentially require
// the PDX Disk Store to exist.
// NOTE this logic could be optimized to include Disk Store, persistent Async Event Queues
// and persistent Regions (either by way of 'persistent' attribute, Data Policy
@@ -124,7 +126,10 @@ public class PdxDiskStoreAwareBeanFactoryPostProcessor implements BeanFactoryPos
* @see org.springframework.beans.factory.config.BeanDefinition#setDependsOn(String[])
*/
private void addPdxDiskStoreDependency(BeanDefinition beanDefinition) {
String[] newDependsOn = (String[]) ArrayUtils.insert(getDependsOn(beanDefinition), 0, getPdxDiskStoreName());
String[] newDependsOn =
(String[]) ArrayUtils.insert(getDependsOn(beanDefinition), 0, getPdxDiskStoreName());
beanDefinition.setDependsOn(newDependsOn);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2018 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
*
* http://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.support;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
* The {@link NoOpBeanFactoryPostProcessor} class is a Spring {@link BeanFactoryPostProcessor} implementation
* that performs no operation.
*
* @author John Blum
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory
* @since 1.0.0
*/
@SuppressWarnings("unused")
public final class NoOpBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public static final NoOpBeanFactoryPostProcessor INSTANCE = new NoOpBeanFactoryPostProcessor();
private NoOpBeanFactoryPostProcessor() { }
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { }
}