SGF-757 - Move configuration of PDX to a PdxConfiguration class imported by the EnablePdx annotation.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -154,7 +154,6 @@ public class ClientCacheConfiguration extends AbstractCacheConfiguration {
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
private List<ClientCacheConfigurer> resolveClientCacheConfigurers() {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
}
|
||||
@@ -18,37 +18,14 @@
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
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.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration.DEFAULT_MCAST_PORT;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
|
||||
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractCacheConfiguration}.
|
||||
@@ -66,183 +43,26 @@ import org.springframework.util.MethodInvoker;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractCacheConfigurationUnitTests {
|
||||
|
||||
@Mock
|
||||
private BeanFactory mockBeanFactory;
|
||||
|
||||
private TestCacheConfiguration cacheConfiguration;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
cacheConfiguration = new TestCacheConfiguration();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T invokeMethod(Object obj, String methodName) throws Exception {
|
||||
|
||||
MethodInvoker methodInvoker = new MethodInvoker();
|
||||
|
||||
methodInvoker.setTargetObject(obj);
|
||||
methodInvoker.setTargetMethod(methodName);
|
||||
methodInvoker.prepare();
|
||||
|
||||
return (T) methodInvoker.invoke();
|
||||
}
|
||||
@Spy
|
||||
private AbstractCacheConfiguration cacheConfiguration;
|
||||
|
||||
@Test
|
||||
public void configurePdxWhenEnablePdxIsConfigured() {
|
||||
public void gemfirePropertiesContainsEssentialProperties() {
|
||||
|
||||
AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class);
|
||||
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class);
|
||||
this.cacheConfiguration.setName("TestName");
|
||||
this.cacheConfiguration.setMcastPort(-1);
|
||||
this.cacheConfiguration.setLogLevel("DEBUG");
|
||||
this.cacheConfiguration.setLocators("skullbox[11235]");
|
||||
this.cacheConfiguration.setStartLocator("boombox[12480]");
|
||||
|
||||
Map<String, Object> annotationAttributes = new HashMap<>(5);
|
||||
Properties gemfireProperties = this.cacheConfiguration.gemfireProperties();
|
||||
|
||||
annotationAttributes.put("diskStoreName", "BlockDiskStore");
|
||||
annotationAttributes.put("ignoreUnreadFields", Boolean.FALSE);
|
||||
annotationAttributes.put("persistent", Boolean.TRUE);
|
||||
annotationAttributes.put("readSerialized", Boolean.TRUE);
|
||||
annotationAttributes.put("serializerBeanName", "MockPdxSerializer");
|
||||
|
||||
when(mockAnnotationMetadata.hasAnnotation(eq(EnablePdx.class.getName()))).thenReturn(true);
|
||||
when(mockAnnotationMetadata.getAnnotationAttributes(eq(EnablePdx.class.getName()))).thenReturn(annotationAttributes);
|
||||
when(mockBeanFactory.containsBean(eq("MockPdxSerializer"))).thenReturn(true);
|
||||
when(mockBeanFactory.getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class))).thenReturn(mockPdxSerializer);
|
||||
|
||||
cacheConfiguration.setBeanFactory(mockBeanFactory);
|
||||
cacheConfiguration.configurePdx(mockAnnotationMetadata);
|
||||
|
||||
assertThat(cacheConfiguration.getPdxDiskStoreName()).isEqualTo("BlockDiskStore");
|
||||
assertThat(cacheConfiguration.getPdxIgnoreUnreadFields()).isFalse();
|
||||
assertThat(cacheConfiguration.getPdxPersistent()).isTrue();
|
||||
assertThat(cacheConfiguration.getPdxReadSerialized()).isTrue();
|
||||
assertThat(cacheConfiguration.getPdxSerializer()).isEqualTo(mockPdxSerializer);
|
||||
|
||||
verify(mockAnnotationMetadata, times(1)).hasAnnotation(eq(EnablePdx.class.getName()));
|
||||
verify(mockAnnotationMetadata, times(1)).getAnnotationAttributes(eq(EnablePdx.class.getName()));
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("MockPdxSerializer"));
|
||||
verify(mockBeanFactory, times(1)).getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePdxWhenEnablePdxIsNotConfigured() {
|
||||
|
||||
AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class);
|
||||
|
||||
when(mockAnnotationMetadata.hasAnnotation(anyString())).thenReturn(false);
|
||||
|
||||
cacheConfiguration.configurePdx(mockAnnotationMetadata);
|
||||
|
||||
assertThat(cacheConfiguration.getPdxDiskStoreName()).isNull();
|
||||
assertThat(cacheConfiguration.getPdxIgnoreUnreadFields()).isNull();
|
||||
assertThat(cacheConfiguration.getPdxPersistent()).isNull();
|
||||
assertThat(cacheConfiguration.getPdxReadSerialized()).isNull();
|
||||
assertThat(cacheConfiguration.getPdxSerializer()).isNull();
|
||||
|
||||
verify(mockAnnotationMetadata, times(1)).hasAnnotation(eq(EnablePdx.class.getName()));
|
||||
verifyNoMoreInteractions(mockAnnotationMetadata);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePdxSerializerUsesPdxSerializerBean() {
|
||||
|
||||
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class);
|
||||
|
||||
when(mockBeanFactory.containsBean(anyString())).thenReturn(true);
|
||||
when(mockBeanFactory.getBean(anyString(), eq(PdxSerializer.class))).thenReturn(mockPdxSerializer);
|
||||
|
||||
cacheConfiguration.setBeanFactory(mockBeanFactory);
|
||||
|
||||
PdxSerializer actualPdxSerializer = cacheConfiguration.resolvePdxSerializer("MockPdxSerializer");
|
||||
|
||||
assertThat(actualPdxSerializer).isEqualTo(mockPdxSerializer);
|
||||
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("MockPdxSerializer"));
|
||||
verify(mockBeanFactory, times(1)).getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePdxSerializerUsesConfiguredPdxSerializer() {
|
||||
|
||||
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class);
|
||||
|
||||
when(mockBeanFactory.containsBean(anyString())).thenReturn(false);
|
||||
|
||||
cacheConfiguration.setBeanFactory(mockBeanFactory);
|
||||
cacheConfiguration.setPdxSerializer(mockPdxSerializer);
|
||||
|
||||
PdxSerializer actualPdxSerializer = cacheConfiguration.resolvePdxSerializer("TestPdxSerializer");
|
||||
|
||||
assertThat(actualPdxSerializer).isEqualTo(mockPdxSerializer);
|
||||
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("TestPdxSerializer"));
|
||||
verify(mockBeanFactory, never()).getBean(anyString(), eq(PdxSerializer.class));
|
||||
verifyZeroInteractions(mockPdxSerializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePdxSerializerCallsNewMappingPdxSerializer() {
|
||||
|
||||
AbstractCacheConfiguration cacheConfigurationSpy = spy(this.cacheConfiguration);
|
||||
MappingPdxSerializer mockPdxSerializer = mock(MappingPdxSerializer.class);
|
||||
|
||||
when(mockBeanFactory.containsBean(anyString())).thenReturn(false);
|
||||
doReturn(mockPdxSerializer).when(cacheConfigurationSpy).newPdxSerializer(any(BeanFactory.class));
|
||||
|
||||
cacheConfigurationSpy.setBeanFactory(mockBeanFactory);
|
||||
|
||||
PdxSerializer actualPdxSerializer = cacheConfigurationSpy.resolvePdxSerializer("TestPdxSerializer");
|
||||
|
||||
assertThat(actualPdxSerializer).isEqualTo(mockPdxSerializer);
|
||||
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("TestPdxSerializer"));
|
||||
verify(mockBeanFactory, never()).getBean(anyString(), eq(PdxSerializer.class));
|
||||
verify(cacheConfigurationSpy, times(1)).newPdxSerializer(eq(mockBeanFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newPdxSerializerUsesConfiguredConversionServiceAndMappingContext() throws Exception {
|
||||
|
||||
ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class);
|
||||
ConversionService mockConversionService = mock(ConversionService.class);
|
||||
GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class);
|
||||
|
||||
when(mockBeanFactory.getConversionService()).thenReturn(mockConversionService);
|
||||
|
||||
cacheConfiguration.setBeanFactory(mockBeanFactory);
|
||||
cacheConfiguration.setMappingContext(mockMappingContext);
|
||||
|
||||
MappingPdxSerializer pdxSerializer = cacheConfiguration.newPdxSerializer();
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getConversionService")).isEqualTo(mockConversionService);
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getMappingContext")).isEqualTo(mockMappingContext);
|
||||
|
||||
verify(mockBeanFactory, times(2)).getConversionService();
|
||||
verifyZeroInteractions(mockConversionService);
|
||||
verifyZeroInteractions(mockMappingContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newPdxSerializerDefaultsConversionServiceAndMappingContextWhenNotConfigured() throws Exception {
|
||||
|
||||
cacheConfiguration.setBeanFactory(mockBeanFactory);
|
||||
|
||||
MappingPdxSerializer pdxSerializer = cacheConfiguration.newPdxSerializer();
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getConversionService")).isInstanceOf(ConversionService.class);
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getMappingContext")).isInstanceOf(GemfireMappingContext.class);
|
||||
}
|
||||
|
||||
protected static class TestCacheConfiguration extends AbstractCacheConfiguration {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotationType() {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends CacheFactoryBean> T newCacheFactoryBean() {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
assertThat(gemfireProperties).isNotNull();
|
||||
assertThat(gemfireProperties).hasSize(5);
|
||||
assertThat(gemfireProperties.getProperty("name")).isEqualTo("TestName");
|
||||
assertThat(gemfireProperties.getProperty("mcast-port")).isEqualTo(String.valueOf(DEFAULT_MCAST_PORT));
|
||||
assertThat(gemfireProperties.getProperty("log-level")).isEqualTo("DEBUG");
|
||||
assertThat(gemfireProperties.getProperty("locators")).isEqualTo("skullbox[11235]");
|
||||
assertThat(gemfireProperties.getProperty("start-locator")).isEqualTo("boombox[12480]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,21 @@
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
@@ -267,9 +271,10 @@ public class EnableGemFirePropertiesIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nameAndGroupGemFirePropertiesAnnotationConfiguration() {
|
||||
public void nameAndGroupsAnnotationBasedGemFirePropertiesConfiguration() {
|
||||
|
||||
this.applicationContext = newApplicationContext(TestNameAndGroupGemFirePropertiesAnnotationConfiguration.class);
|
||||
this.applicationContext =
|
||||
newApplicationContext(TestNameAndGroupsAnnotationBasedGemFirePropertiesConfiguration.class);
|
||||
|
||||
assertThat(this.applicationContext).isNotNull();
|
||||
assertThat(this.applicationContext.containsBean("gemfireCache")).isTrue();
|
||||
@@ -319,6 +324,37 @@ public class EnableGemFirePropertiesIntegrationTests {
|
||||
assertThat(gemfireProperties.getProperty("off-heap-memory-size")).isEqualTo("1024g");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pdxGemFirePropertiesConfiguration() {
|
||||
|
||||
PropertySource testPropertySource = new MockPropertySource("TestPropertySource")
|
||||
.withProperty("spring.data.gemfire.pdx.disk-store-name", "TestDiskStore")
|
||||
.withProperty("spring.data.gemfire.pdx.ignore-unread-fields", "true")
|
||||
.withProperty("spring.data.gemfire.pdx.persistent", "true")
|
||||
.withProperty("spring.data.gemfire.pdx.read-serialized", "true")
|
||||
.withProperty("spring.data.gemfire.pdx.serializer-bean-name", "mockPdxSerializer");
|
||||
|
||||
this.applicationContext =
|
||||
newApplicationContext(testPropertySource, TestPdxGemFirePropertiesConfiguration.class);
|
||||
|
||||
assertThat(this.applicationContext).isNotNull();
|
||||
assertThat(this.applicationContext.containsBean("gemfireCache")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("mockPdxSerializer")).isTrue();
|
||||
|
||||
CacheFactoryBean gemfireCache = this.applicationContext.getBean("&gemfireCache", CacheFactoryBean.class);
|
||||
|
||||
assertThat(gemfireCache).isNotNull();
|
||||
assertThat(gemfireCache.getPdxDiskStoreName()).isEqualTo("TestDiskStore");
|
||||
assertThat(gemfireCache.getPdxIgnoreUnreadFields()).isTrue();
|
||||
assertThat(gemfireCache.getPdxPersistent()).isTrue();
|
||||
assertThat(gemfireCache.getPdxReadSerialized()).isTrue();
|
||||
|
||||
PdxSerializer mockPdxSerializer = this.applicationContext.getBean("mockPdxSerializer", PdxSerializer.class);
|
||||
|
||||
assertThat(mockPdxSerializer).isNotNull();
|
||||
assertThat(gemfireCache.getPdxSerializer()).isEqualTo(mockPdxSerializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redisServerGemFirePropertiesConfiguration() {
|
||||
|
||||
@@ -515,7 +551,7 @@ public class EnableGemFirePropertiesIntegrationTests {
|
||||
@EnableGemFireMockObjects
|
||||
@PeerCacheApplication
|
||||
@EnableGemFireProperties(name = "TestName", groups = { "TestGroupOne", "TestGroupTwo" })
|
||||
static class TestNameAndGroupGemFirePropertiesAnnotationConfiguration { }
|
||||
static class TestNameAndGroupsAnnotationBasedGemFirePropertiesConfiguration { }
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@PeerCacheApplication
|
||||
@@ -523,6 +559,18 @@ public class EnableGemFirePropertiesIntegrationTests {
|
||||
@EnableOffHeap(memorySize = "64g")
|
||||
static class TestOffHeapGemFirePropertiesConfiguration { }
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@PeerCacheApplication
|
||||
@EnablePdx
|
||||
@SuppressWarnings("unused")
|
||||
static class TestPdxGemFirePropertiesConfiguration {
|
||||
|
||||
@Bean
|
||||
PdxSerializer mockPdxSerializer() {
|
||||
return mock(PdxSerializer.class);
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@PeerCacheApplication
|
||||
@EnableGemFireProperties
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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 static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.DiskStoreFactoryBean;
|
||||
import org.springframework.data.gemfire.LocalRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
|
||||
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
|
||||
|
||||
/**
|
||||
* The EnablePdxConfigurationIntegrationTests class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class EnablePdxConfigurationIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close);
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
|
||||
return new AnnotationConfigApplicationContext(annotatedClasses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionBeanDefinitionDependsOnPdxDiskStoreBean() {
|
||||
|
||||
this.applicationContext = newApplicationContext(TestEnablePdxWithDiskStoreConfiguration.class);
|
||||
|
||||
assertThat(this.applicationContext).isNotNull();
|
||||
assertThat(this.applicationContext.containsBean("gemfireCache")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("MockPdxSerializer")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("TestDiskStore")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("TestRegion")).isTrue();
|
||||
|
||||
CacheFactoryBean gemfireCache = this.applicationContext.getBean("&gemfireCache", CacheFactoryBean.class);
|
||||
|
||||
assertThat(gemfireCache).isNotNull();
|
||||
assertThat(gemfireCache.getPdxSerializer())
|
||||
.isEqualTo(this.applicationContext.getBean("MockPdxSerializer", PdxSerializer.class));
|
||||
|
||||
BeanDefinition testDiskStoreBeanDefinition =
|
||||
this.applicationContext.getBeanFactory().getBeanDefinition("TestDiskStore");
|
||||
|
||||
assertThat(testDiskStoreBeanDefinition).isNotNull();
|
||||
assertThat(testDiskStoreBeanDefinition.getDependsOn()).isNullOrEmpty();
|
||||
|
||||
BeanDefinition testRegionBeanDefinition =
|
||||
this.applicationContext.getBeanFactory().getBeanDefinition("TestRegion");
|
||||
|
||||
assertThat(testRegionBeanDefinition).isNotNull();
|
||||
assertThat(testRegionBeanDefinition.getDependsOn()).containsExactly("TestDiskStore");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionBeanDefinitionHasNoDependencies() {
|
||||
|
||||
this.applicationContext = newApplicationContext(TestEnablePdxConfigurationWithNoDiskStoreConfiguration.class);
|
||||
|
||||
assertThat(this.applicationContext).isNotNull();
|
||||
assertThat(this.applicationContext.containsBean("gemfireCache")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("TestDiskStore")).isTrue();
|
||||
assertThat(this.applicationContext.containsBean("TestRegion")).isTrue();
|
||||
|
||||
CacheFactoryBean gemfireCache = this.applicationContext.getBean("&gemfireCache", CacheFactoryBean.class);
|
||||
|
||||
assertThat(gemfireCache).isNotNull();
|
||||
assertThat(gemfireCache.getPdxSerializer()).isInstanceOf(MappingPdxSerializer.class);
|
||||
|
||||
BeanDefinition testDiskStoreBeanDefinition =
|
||||
this.applicationContext.getBeanFactory().getBeanDefinition("TestDiskStore");
|
||||
|
||||
assertThat(testDiskStoreBeanDefinition).isNotNull();
|
||||
assertThat(testDiskStoreBeanDefinition.getDependsOn()).isNullOrEmpty();
|
||||
|
||||
BeanDefinition testRegionBeanDefinition =
|
||||
this.applicationContext.getBeanFactory().getBeanDefinition("TestRegion");
|
||||
|
||||
assertThat(testRegionBeanDefinition).isNotNull();
|
||||
assertThat(testRegionBeanDefinition.getDependsOn()).isNullOrEmpty();
|
||||
|
||||
}
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@PeerCacheApplication
|
||||
@EnablePdx(diskStoreName = "TestDiskStore", serializerBeanName = "MockPdxSerializer")
|
||||
@SuppressWarnings("unused")
|
||||
static class TestEnablePdxWithDiskStoreConfiguration {
|
||||
|
||||
@Bean("TestDiskStore")
|
||||
DiskStoreFactoryBean testPdxDiskStore(GemFireCache gemfireCache) {
|
||||
|
||||
DiskStoreFactoryBean testDiskStore = new DiskStoreFactoryBean();
|
||||
|
||||
testDiskStore.setCache(gemfireCache);
|
||||
|
||||
return testDiskStore;
|
||||
}
|
||||
|
||||
@Bean("TestRegion")
|
||||
LocalRegionFactoryBean<Object, Object> testRegion(GemFireCache gemfireCache) {
|
||||
|
||||
LocalRegionFactoryBean<Object, Object> testRegion = new LocalRegionFactoryBean<>();
|
||||
|
||||
testRegion.setCache(gemfireCache);
|
||||
testRegion.setClose(false);
|
||||
testRegion.setPersistent(false);
|
||||
|
||||
return testRegion;
|
||||
}
|
||||
|
||||
@Bean("MockPdxSerializer")
|
||||
PdxSerializer mockPdxSerializer() {
|
||||
return mock(PdxSerializer.class);
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@ClientCacheApplication
|
||||
@EnablePdx
|
||||
@SuppressWarnings("unused")
|
||||
static class TestEnablePdxConfigurationWithNoDiskStoreConfiguration {
|
||||
|
||||
@Bean("TestDiskStore")
|
||||
DiskStoreFactoryBean testPdxDiskStore(GemFireCache gemfireCache) {
|
||||
|
||||
DiskStoreFactoryBean testDiskStore = new DiskStoreFactoryBean();
|
||||
|
||||
testDiskStore.setCache(gemfireCache);
|
||||
|
||||
return testDiskStore;
|
||||
}
|
||||
|
||||
@Bean("TestRegion")
|
||||
public ClientRegionFactoryBean<Object, Object> testRegion(GemFireCache gemfireCache) {
|
||||
|
||||
ClientRegionFactoryBean<Object, Object> testRegion = new ClientRegionFactoryBean<>();
|
||||
|
||||
testRegion.setCache(gemfireCache);
|
||||
testRegion.setClose(false);
|
||||
testRegion.setShortcut(ClientRegionShortcut.LOCAL);
|
||||
|
||||
return testRegion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* 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 static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.pdx.PdxSerializer;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
|
||||
import org.springframework.data.gemfire.mapping.MappingPdxSerializer;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EnablePdx} and {@link PdxConfiguration}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Spy
|
||||
* @see org.apache.geode.pdx.PdxSerializer
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnablePdx
|
||||
* @see org.springframework.data.gemfire.config.annotation.PdxConfiguration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class EnablePdxConfigurationUnitTests {
|
||||
|
||||
@Spy
|
||||
private PdxConfiguration pdxConfiguration;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T invokeMethod(Object obj, String methodName) throws Exception {
|
||||
|
||||
MethodInvoker methodInvoker = new MethodInvoker();
|
||||
|
||||
methodInvoker.setTargetObject(obj);
|
||||
methodInvoker.setTargetMethod(methodName);
|
||||
methodInvoker.prepare();
|
||||
|
||||
return (T) methodInvoker.invoke();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setImportMetadataWhenEnablePdxIsConfigured() {
|
||||
|
||||
AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class);
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
Map<String, Object> annotationAttributes = new HashMap<>(5);
|
||||
|
||||
annotationAttributes.put("diskStoreName", "MockDiskStore");
|
||||
annotationAttributes.put("ignoreUnreadFields", Boolean.TRUE);
|
||||
annotationAttributes.put("persistent", Boolean.TRUE);
|
||||
annotationAttributes.put("readSerialized", Boolean.TRUE);
|
||||
annotationAttributes.put("serializerBeanName", "MockPdxSerializer");
|
||||
|
||||
when(mockAnnotationMetadata.hasAnnotation(eq(EnablePdx.class.getName()))).thenReturn(true);
|
||||
when(mockAnnotationMetadata.getAnnotationAttributes(eq(EnablePdx.class.getName())))
|
||||
.thenReturn(annotationAttributes);
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
this.pdxConfiguration.setImportMetadata(mockAnnotationMetadata);
|
||||
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.getDiskStoreName().orElse(null)).isEqualTo("MockDiskStore");
|
||||
assertThat(this.pdxConfiguration.isIgnoreUnreadFields()).isTrue();
|
||||
assertThat(this.pdxConfiguration.isPersistent()).isTrue();
|
||||
assertThat(this.pdxConfiguration.isReadSerialized()).isTrue();
|
||||
assertThat(this.pdxConfiguration.getSerializerBeanName().orElse(null)).isEqualTo("MockPdxSerializer");
|
||||
|
||||
verify(mockAnnotationMetadata, times(1)).hasAnnotation(eq(EnablePdx.class.getName()));
|
||||
verify(mockAnnotationMetadata, times(1))
|
||||
.getAnnotationAttributes(eq(EnablePdx.class.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setImportMetadataWhenEnablePdxIsNotConfigured() {
|
||||
|
||||
AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class);
|
||||
|
||||
when(mockAnnotationMetadata.hasAnnotation(anyString())).thenReturn(false);
|
||||
|
||||
this.pdxConfiguration.setImportMetadata(mockAnnotationMetadata);
|
||||
|
||||
assertThat(this.pdxConfiguration.getDiskStoreName().isPresent()).isFalse();
|
||||
assertThat(this.pdxConfiguration.isIgnoreUnreadFields()).isFalse();
|
||||
assertThat(this.pdxConfiguration.isPersistent()).isFalse();
|
||||
assertThat(this.pdxConfiguration.isReadSerialized()).isFalse();
|
||||
assertThat(this.pdxConfiguration.getSerializerBeanName().isPresent()).isFalse();
|
||||
|
||||
verify(mockAnnotationMetadata, times(1)).hasAnnotation(eq(EnablePdx.class.getName()));
|
||||
verifyNoMoreInteractions(mockAnnotationMetadata);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuresPdxForCacheFactoryBean() {
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class);
|
||||
|
||||
when(mockBeanFactory.containsBean(eq("MockPdxSerializer"))).thenReturn(true);
|
||||
when(mockBeanFactory.getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class)))
|
||||
.thenReturn(mockPdxSerializer);
|
||||
|
||||
doReturn(Optional.of("MockPdxDiskStore")).when(this.pdxConfiguration).getDiskStoreName();
|
||||
doReturn(true).when(this.pdxConfiguration).isIgnoreUnreadFields();
|
||||
doReturn(true).when(this.pdxConfiguration).isPersistent();
|
||||
doReturn(true).when(this.pdxConfiguration).isReadSerialized();
|
||||
doReturn(Optional.of("MockPdxSerializer")).when(this.pdxConfiguration).getSerializerBeanName();
|
||||
|
||||
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
this.pdxConfiguration.configurePdx(cacheFactoryBean);
|
||||
|
||||
assertThat(cacheFactoryBean.getPdxDiskStoreName()).isEqualTo("MockPdxDiskStore");
|
||||
assertThat(cacheFactoryBean.getPdxIgnoreUnreadFields()).isTrue();
|
||||
assertThat(cacheFactoryBean.getPdxPersistent()).isTrue();
|
||||
assertThat(cacheFactoryBean.getPdxReadSerialized()).isTrue();
|
||||
assertThat(cacheFactoryBean.getPdxSerializer()).isEqualTo(mockPdxSerializer);
|
||||
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("MockPdxSerializer"));
|
||||
verify(mockBeanFactory, times(1))
|
||||
.getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class));
|
||||
|
||||
verify(this.pdxConfiguration, times(1)).getDiskStoreName();
|
||||
verify(this.pdxConfiguration, times(1)).isIgnoreUnreadFields();
|
||||
verify(this.pdxConfiguration, times(1)).isPersistent();
|
||||
verify(this.pdxConfiguration, times(1)).isReadSerialized();
|
||||
verify(this.pdxConfiguration, times(1)).getSerializerBeanName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveConversionServiceWithNonConfigurableBeanFactoryReturnsNull() {
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.resolveConversionService().isPresent()).isFalse();
|
||||
|
||||
verifyZeroInteractions(mockBeanFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveConversionServiceReturnsConfiguredConversionService() {
|
||||
|
||||
ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class);
|
||||
|
||||
ConversionService mockConversionService = mock(ConversionService.class);
|
||||
|
||||
when(mockBeanFactory.getConversionService()).thenReturn(mockConversionService);
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.resolveConversionService().orElse(null))
|
||||
.isEqualTo(mockConversionService);
|
||||
|
||||
verify(mockBeanFactory, atLeastOnce()).getConversionService();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void resolveMappingContextWhenBeanFactoryDoesNotContainMappingContextBeanReturnsNull() {
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
when(mockBeanFactory.getBean(any(Class.class))).thenThrow(new NoSuchBeanDefinitionException("test"));
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.resolveMappingContext().isPresent()).isFalse();
|
||||
|
||||
verify(mockBeanFactory, times(1)).getBean(eq(GemfireMappingContext.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveMappingContextReturnsConfiguredMappingContext() {
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class);
|
||||
|
||||
when(mockBeanFactory.getBean(eq(GemfireMappingContext.class))).thenReturn(mockMappingContext);
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.resolveMappingContext().orElse(null)).isEqualTo(mockMappingContext);
|
||||
|
||||
verify(mockBeanFactory, times(1)).getBean(eq(GemfireMappingContext.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePdxSerializerWhenBeanFactoryDoesNotContainPdxSerializerBeanReturnsMappingPdxSerializer() {
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
when(mockBeanFactory.containsBean(anyString())).thenReturn(false);
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
this.pdxConfiguration.setSerializerBeanName("MockPdxSerializer");
|
||||
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.getSerializerBeanName().orElse(null)).isEqualTo("MockPdxSerializer");
|
||||
assertThat(this.pdxConfiguration.resolvePdxSerializer()).isInstanceOf(MappingPdxSerializer.class);
|
||||
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("MockPdxSerializer"));
|
||||
verify(mockBeanFactory, never()).getBean(anyString(), any(PdxSerializer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePdxSerializerReturnsConfiguredPdxSerializer() {
|
||||
|
||||
BeanFactory mockBeanFactory = mock(BeanFactory.class);
|
||||
|
||||
PdxSerializer mockPdxSerializer = mock(PdxSerializer.class);
|
||||
|
||||
when(mockBeanFactory.containsBean(eq("MockPdxSerializer"))).thenReturn(true);
|
||||
when(mockBeanFactory.getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class)))
|
||||
.thenReturn(mockPdxSerializer);
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
this.pdxConfiguration.setSerializerBeanName("MockPdxSerializer");
|
||||
|
||||
assertThat(this.pdxConfiguration.getBeanFactory()).isEqualTo(mockBeanFactory);
|
||||
assertThat(this.pdxConfiguration.getSerializerBeanName().orElse(null)).isEqualTo("MockPdxSerializer");
|
||||
assertThat(this.pdxConfiguration.resolvePdxSerializer()).isEqualTo(mockPdxSerializer);
|
||||
|
||||
verify(mockBeanFactory, times(1)).containsBean(eq("MockPdxSerializer"));
|
||||
verify(mockBeanFactory, times(1))
|
||||
.getBean(eq("MockPdxSerializer"), eq(PdxSerializer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newPdxSerializerReturnsMappingPdxSerializerConfiguredWithResolvedConversionServiceAndMappingContext()
|
||||
throws Exception {
|
||||
|
||||
ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class);
|
||||
|
||||
ConversionService mockConversionService = mock(ConversionService.class);
|
||||
|
||||
GemfireMappingContext mockMappingContext = mock(GemfireMappingContext.class);
|
||||
|
||||
when(mockBeanFactory.getBean(eq(GemfireMappingContext.class))).thenReturn(mockMappingContext);
|
||||
when(mockBeanFactory.getConversionService()).thenReturn(mockConversionService);
|
||||
|
||||
this.pdxConfiguration.setBeanFactory(mockBeanFactory);
|
||||
|
||||
PdxSerializer pdxSerializer = this.pdxConfiguration.newPdxSerializer();
|
||||
|
||||
assertThat(pdxSerializer).isInstanceOf(MappingPdxSerializer.class);
|
||||
|
||||
assertThat(this.<Object>invokeMethod(pdxSerializer, "getConversionService"))
|
||||
.isEqualTo(mockConversionService);
|
||||
|
||||
assertThat(this.<Object>invokeMethod(pdxSerializer, "getMappingContext"))
|
||||
.isEqualTo(mockMappingContext);
|
||||
|
||||
verify(mockBeanFactory, times(1)).getBean(eq(GemfireMappingContext.class));
|
||||
verify(mockBeanFactory, atLeastOnce()).getConversionService();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user