diff --git a/pom.xml b/pom.xml
index 879c7091..02d60fe8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,6 +16,9 @@
Spring Data GemFire
+ SGF
+ spring.data.gemfire
+ 1.8
2.7.7
1.3.2
3.6.2
@@ -23,9 +26,9 @@
9.1.1
2.0.2
1.01
+ 0.4
2.1.0.BUILD-SNAPSHOT
1.2.0.RELEASE
- spring.data.gemfire
@@ -149,7 +152,14 @@
true
-
+
+ org.iq80.snappy
+ snappy
+ ${snappy.version}
+ true
+
+
+
org.aspectj
aspectjweaver
diff --git a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java
index 9db2886f..24c67812 100644
--- a/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/RegionFactoryBean.java
@@ -49,6 +49,7 @@ import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
import org.apache.geode.cache.wan.GatewaySender;
+import org.apache.geode.compression.Compressor;
import org.apache.geode.internal.cache.UserSpecifiedRegionAttributes;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
@@ -125,6 +126,8 @@ public abstract class RegionFactoryBean extends RegionLookupFactoryBean keyConstraint;
private Class valueConstraint;
+ private Compressor compressor;
+
private DataPolicy dataPolicy;
private EvictionAttributes evictionAttributes;
@@ -310,6 +313,8 @@ public abstract class RegionFactoryBean extends RegionLookupFactoryBean extends RegionLookupFactoryBean extends RegionLookupFactoryBean
private ClientRegionShortcut shortcut;
+ private Compressor compressor;
+
private DataPolicy dataPolicy;
private EvictionAttributes evictionAttributes;
@@ -391,6 +394,8 @@ public class ClientRegionFactoryBean extends RegionLookupFactoryBean
stream(nullSafeArray(this.cacheListeners, CacheListener.class)).forEach(clientRegionFactory::addCacheListener);
+ Optional.ofNullable(this.compressor).ifPresent(clientRegionFactory::setCompressor);
+
Optional.ofNullable(this.diskStoreName).filter(StringUtils::hasText)
.ifPresent(clientRegionFactory::setDiskStoreName);
@@ -560,6 +565,16 @@ public class ClientRegionFactoryBean extends RegionLookupFactoryBean
this.destroy = (this.destroy && !close); // retain previous value iff close is false.
}
+ /**
+ * Configures the {@link Compressor} used to compress the this {@link Region Region's} data.
+ *
+ * @param compressor {@link Compressor} used to compress the this {@link Region Region's} data.
+ * @see org.apache.geode.compression.Compressor
+ */
+ public void setCompressor(Compressor compressor) {
+ this.compressor = compressor;
+ }
+
/**
* Sets the Data Policy. Used only when a new Region is created.
*
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/CompressionConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/CompressionConfiguration.java
new file mode 100644
index 00000000..bdf9b76c
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/CompressionConfiguration.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2017 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 java.util.Arrays.stream;
+import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
+import static org.springframework.data.gemfire.util.CollectionUtils.asSet;
+import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.compression.Compressor;
+import org.apache.geode.compression.SnappyCompressor;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+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.type.AnnotationMetadata;
+import org.springframework.data.gemfire.RegionLookupFactoryBean;
+import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
+import org.springframework.data.gemfire.util.CollectionUtils;
+import org.springframework.data.gemfire.util.SpringUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * The {@link CompressionConfiguration} class is a Spring {@link ImportAware} implementation capable of
+ * enabling Pivotal GemFire/Apache Geode cache {@link Region Regions} data compression.
+ *
+ * @author John Blum
+ * @see org.apache.geode.cache.Region
+ * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
+ * @see org.springframework.context.annotation.Bean
+ * @see org.springframework.context.annotation.Configuration
+ * @see org.springframework.context.annotation.ImportAware
+ * @see org.springframework.data.gemfire.config.annotation.EnableCompression
+ * @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
+ * @since 2.0.2
+ */
+@Configuration
+@SuppressWarnings("unused")
+public class CompressionConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
+
+ protected static final String SNAPPY_COMPRESSOR_BEAN_NAME = "SnappyCompressor";
+
+ private String compressorBeanName = SNAPPY_COMPRESSOR_BEAN_NAME;
+
+ private Set regionNames = new HashSet<>();
+
+ /**
+ * Returns the {@link EnableCompression} {@link Annotation} {@link Class} type.
+ *
+ * @return the {@link EnableCompression} {@link Annotation} {@link Class} type.
+ * @see org.springframework.data.gemfire.config.annotation.EnableOffHeap
+ * @see java.lang.annotation.Annotation
+ */
+ @Override
+ protected Class extends Annotation> getAnnotationType() {
+ return EnableCompression.class;
+ }
+
+ public void setCompressorBeanName(String compressorBeanName) {
+ this.compressorBeanName = compressorBeanName;
+ }
+
+ protected String resolveCompressorBeanName() {
+ return Optional.ofNullable(this.compressorBeanName).filter(StringUtils::hasText)
+ .orElse(SNAPPY_COMPRESSOR_BEAN_NAME);
+ }
+
+ public void setRegionNames(String[] regionNames) {
+ setRegionNames(asSet(nullSafeArray(regionNames, String.class)));
+ }
+
+ public void setRegionNames(Iterable regionNames) {
+ this.regionNames = CollectionUtils.addAll(this.regionNames, nullSafeIterable(regionNames));
+ }
+
+ protected Set resolveRegionNames() {
+ return Collections.unmodifiableSet(this.regionNames);
+ }
+
+ @Override
+ public void setImportMetadata(AnnotationMetadata importingClassMetadata) {
+
+ if (isAnnotationPresent(importingClassMetadata)) {
+
+ AnnotationAttributes enableCompressionAttributes = getAnnotationAttributes(importingClassMetadata);
+
+ setCompressorBeanName(resolveProperty(cacheCompressionProperty("compressor-bean-name"),
+ enableCompressionAttributes.getString("compressorBeanName")));
+
+ setRegionNames(resolveProperty(cacheCompressionProperty("region-names"),
+ String[].class, enableCompressionAttributes.getStringArray("regionNames")));
+ }
+ }
+
+ @Bean(SNAPPY_COMPRESSOR_BEAN_NAME)
+ Compressor snappyCompressor() {
+ return new SnappyCompressor();
+ }
+
+ @Bean
+ BeanFactoryPostProcessor regionCompressionBeanFactoryPostProcessor() {
+
+ String resolvedCompressorBeanName = resolveCompressorBeanName();
+
+ return beanFactory ->
+ stream(nullSafeArray(beanFactory.getBeanDefinitionNames(), String.class)).forEach(beanName ->
+ Optional.of(beanFactory.getBeanDefinition(beanName))
+ .filter(beanDefinition -> isTargetedRegionBean(beanName, beanDefinition, beanFactory))
+ .ifPresent(beanDefinition -> SpringUtils.setPropertyReference(
+ beanDefinition, "compressor", resolvedCompressorBeanName)));
+ }
+
+ private boolean isTargetedRegionBean(String beanName, BeanDefinition beanDefinition,
+ ConfigurableListableBeanFactory beanFactory) {
+
+ return isNamedRegion(beanName, beanDefinition, beanFactory) && isRegionBean(beanDefinition, beanFactory);
+ }
+
+ private boolean isRegionBean(BeanDefinition beanDefinition, ConfigurableListableBeanFactory beanFactory) {
+
+ return Optional.ofNullable(beanDefinition)
+ .flatMap(it -> resolveBeanClass(it, beanFactory.getBeanClassLoader()))
+ .filter(beanClass -> RegionLookupFactoryBean.class.isAssignableFrom(beanClass))
+ .isPresent();
+ }
+
+ private boolean isNamedRegion(String beanName, BeanDefinition beanDefinition,
+ ConfigurableListableBeanFactory beanFactory) {
+
+ Set resolvedRegionNames = resolveRegionNames();
+
+ return CollectionUtils.isEmpty(resolvedRegionNames)
+ || CollectionUtils.containsAny(resolvedRegionNames, resolveBeanNames(beanName, beanDefinition, beanFactory));
+ }
+
+ private Collection resolveBeanNames(String beanName, BeanDefinition beanDefinition,
+ ConfigurableListableBeanFactory beanFactory) {
+
+ Collection beanNames = new HashSet<>();
+
+ beanNames.add(beanName);
+
+ Collections.addAll(beanNames, beanFactory.getAliases(beanName));
+
+ PropertyValue regionName = beanDefinition.getPropertyValues().getPropertyValue("regionName");
+
+ if (regionName != null) {
+
+ Object regionNameValue = regionName.getValue();
+
+ if (regionNameValue != null) {
+ beanNames.add(regionNameValue.toString());
+ }
+ }
+
+ return beanNames;
+ }
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableCompression.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableCompression.java
new file mode 100644
index 00000000..ae01b0a8
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableCompression.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2017 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.springframework.data.gemfire.config.annotation.CompressionConfiguration.SNAPPY_COMPRESSOR_BEAN_NAME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.geode.cache.Region;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * The {@link EnableCompression} annotation marks a Spring {@link Configuration @Configuration} annotated application
+ * {@link Class} to configure and enable Pivotal GemFire/Apache Geode {@link Region} data compression.
+ *
+ * @author John Blum
+ * @see java.lang.annotation.Annotation
+ * @see org.springframework.context.annotation.Import
+ * @see org.springframework.data.gemfire.config.annotation.CompressionConfiguration
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@Import(CompressionConfiguration.class)
+public @interface EnableCompression {
+
+ /**
+ * Reference to the {@link String name} of a bean having type {@link org.apache.geode.compression.Compressor}
+ * registered in the Spring container to handle {@link Region} compression.
+ *
+ * Defaults to {@literal snappyCompressor}.
+ *
+ * Set the {@literal spring.data.gemfire.cache.compression.compressor-bean-name}
+ * in {@literal application.properties}.
+ */
+ String compressorBeanName() default SNAPPY_COMPRESSOR_BEAN_NAME;
+
+ /**
+ * Identifies all the {@link Region Regions} by name in which the data compression will be enabled.
+ *
+ * Defaults to all {@link Region Regions}.
+ *
+ * Set the {@literal spring.data.gemfire.cache.compression.region-names} property
+ * in {@literal application.properties}.
+ */
+ String[] regionNames() default {};
+
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/OffHeapConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/OffHeapConfiguration.java
index ebd9ad68..4666f38a 100644
--- a/src/main/java/org/springframework/data/gemfire/config/annotation/OffHeapConfiguration.java
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/OffHeapConfiguration.java
@@ -32,7 +32,6 @@ import java.util.Set;
import org.apache.geode.cache.Region;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
-import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -48,11 +47,15 @@ import org.springframework.data.gemfire.util.PropertiesBuilder;
/**
* The {@link OffHeapConfiguration} class is a Spring {@link ImportBeanDefinitionRegistrar} capable of
- * enabling Pivotal GemFire/Apache Geode cache {@link Region Regions} to use Off-Heap memory for data storage.
+ * enabling Pivotal GemFire/Apache Geode cache {@link Region Regions} to use Off-Heap Memory for data storage.
*
* @author John Blum
+ * @see java.util.Properties
+ * @see org.apache.geode.cache.Region
+ * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
* @see org.springframework.data.gemfire.config.annotation.EnableOffHeap
+ * @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
* @since 1.9.0
*/
@@ -121,13 +124,13 @@ public class OffHeapConfiguration extends EmbeddedServiceConfigurationSupport {
.addPropertyValue("offHeap", true)));
}
- boolean isTargetedRegionBean(String beanName, BeanDefinition beanDefinition,
+ private boolean isTargetedRegionBean(String beanName, BeanDefinition beanDefinition,
ConfigurableListableBeanFactory beanFactory) {
return isNamedRegion(beanName, beanDefinition, beanFactory) && isRegionBean(beanDefinition, beanFactory);
}
- boolean isRegionBean(BeanDefinition beanDefinition, ConfigurableListableBeanFactory beanFactory) {
+ private boolean isRegionBean(BeanDefinition beanDefinition, ConfigurableListableBeanFactory beanFactory) {
return Optional.ofNullable(beanDefinition)
.flatMap(it -> resolveBeanClass(it, beanFactory.getBeanClassLoader()))
@@ -135,13 +138,15 @@ public class OffHeapConfiguration extends EmbeddedServiceConfigurationSupport {
.isPresent();
}
- boolean isNamedRegion(String beanName, BeanDefinition beanDefinition, BeanFactory beanFactory) {
+ private boolean isNamedRegion(String beanName, BeanDefinition beanDefinition,
+ ConfigurableListableBeanFactory beanFactory) {
return CollectionUtils.isEmpty(regionNames)
- || CollectionUtils.containsAny(regionNames, getBeanNames(beanName, beanDefinition, beanFactory));
+ || CollectionUtils.containsAny(regionNames, resolveBeanNames(beanName, beanDefinition, beanFactory));
}
- Collection getBeanNames(String beanName, BeanDefinition beanDefinition, BeanFactory beanFactory) {
+ private Collection resolveBeanNames(String beanName, BeanDefinition beanDefinition,
+ ConfigurableListableBeanFactory beanFactory) {
Collection beanNames = new HashSet<>();
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java
index 1fa850f1..59964abe 100644
--- a/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/CacheTypeAwareRegionFactoryBean.java
@@ -33,6 +33,7 @@ import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.compression.Compressor;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.GenericRegionFactoryBean;
@@ -61,6 +62,7 @@ import org.springframework.util.StringUtils;
* @see org.apache.geode.cache.Scope
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.client.ClientRegionShortcut
+ * @see org.apache.geode.compression.Compressor
* @see org.springframework.data.gemfire.GenericRegionFactoryBean
* @see org.springframework.data.gemfire.LocalRegionFactoryBean
* @see org.springframework.data.gemfire.PartitionedRegionFactoryBean
@@ -84,6 +86,8 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe
private ClientRegionShortcut clientRegionShortcut = ClientRegionShortcut.PROXY;
+ private Compressor compressor;
+
private DataPolicy dataPolicy = DataPolicy.DEFAULT;
private List regionConfigurers = Collections.emptyList();
@@ -129,6 +133,7 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe
clientRegionFactory.setBeanFactory(getBeanFactory());
clientRegionFactory.setCache(gemfireCache);
clientRegionFactory.setClose(isClose());
+ clientRegionFactory.setCompressor(getCompressor());
clientRegionFactory.setDiskStoreName(getDiskStoreName());
clientRegionFactory.setKeyConstraint(getKeyConstraint());
clientRegionFactory.setLookupEnabled(getLookupEnabled());
@@ -178,6 +183,7 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe
serverRegionFactory.setBeanFactory(getBeanFactory());
serverRegionFactory.setCache(gemfireCache);
serverRegionFactory.setClose(isClose());
+ serverRegionFactory.setCompressor(getCompressor());
serverRegionFactory.setDataPolicy(getDataPolicy());
serverRegionFactory.setDiskStoreName(getDiskStoreName());
serverRegionFactory.setKeyConstraint(getKeyConstraint());
@@ -254,6 +260,26 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe
return Boolean.TRUE.equals(getClose());
}
+ /**
+ * Configures the {@link Compressor} used to compress the this {@link Region Region's} data.
+ *
+ * @param compressor {@link Compressor} used to compress the this {@link Region Region's} data.
+ * @see org.apache.geode.compression.Compressor
+ */
+ public void setCompressor(Compressor compressor) {
+ this.compressor = compressor;
+ }
+
+ /**
+ * Returns the configured {@link Compressor} used to compress the this {@link Region Region's} data.
+ *
+ * @return the configured {@link Compressor} used to compress the this {@link Region Region's} data.
+ * @see org.apache.geode.compression.Compressor
+ */
+ protected Compressor getCompressor() {
+ return this.compressor;
+ }
+
public void setDataPolicy(DataPolicy dataPolicy) {
this.dataPolicy = dataPolicy;
}
@@ -278,10 +304,21 @@ public class CacheTypeAwareRegionFactoryBean extends RegionLookupFactoryBe
return this.keyConstraint;
}
+ /**
+ * Configure the {@link Region} to manage data in Off-Heap Memory.
+ *
+ * @param offHeap boolean value indicating whether the {@link Region Region's} data
+ * will be managed in Off-Heap Memory.
+ */
public void setOffHeap(Boolean offHeap) {
this.offHeap = offHeap;
}
+ /**
+ * Return the configuration setting for whether the {@link Region Region's} data will be managed in Off-Heap Memory.
+ *
+ * @return a boolean value indicating whether the {@link Region Region's} data will be managed in Off-Heap Memory.
+ */
protected Boolean getOffHeap() {
return this.offHeap;
}
diff --git a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java
index 8d6ede51..4e6ecc24 100644
--- a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java
+++ b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java
@@ -29,6 +29,7 @@ import java.util.function.Supplier;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.util.StringUtils;
/**
@@ -53,6 +54,24 @@ public abstract class SpringUtils {
return bean;
}
+ /* (non-Javadoc) */
+ public static BeanDefinition setPropertyReference(BeanDefinition beanDefinition,
+ String propertyName, String beanName) {
+
+ beanDefinition.getPropertyValues().addPropertyValue(propertyName, new RuntimeBeanReference(beanName));
+
+ return beanDefinition;
+ }
+
+ /* (non-Javadoc) */
+ public static BeanDefinition setPropertyValue(BeanDefinition beanDefinition,
+ String propertyName, Object propertyValue) {
+
+ beanDefinition.getPropertyValues().addPropertyValue(propertyName, propertyValue);
+
+ return beanDefinition;
+ }
+
/* (non-Javadoc) */
public static String defaultIfEmpty(String value, String defaultValue) {
return (StringUtils.hasText(value) ? value : defaultValue);
diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCompressionConfigurationUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCompressionConfigurationUnitTests.java
new file mode 100644
index 00000000..5b72ba6d
--- /dev/null
+++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableCompressionConfigurationUnitTests.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2017 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 static org.springframework.data.gemfire.config.annotation.CompressionConfiguration.SNAPPY_COMPRESSOR_BEAN_NAME;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+import org.apache.geode.cache.GemFireCache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.compression.Compressor;
+import org.apache.geode.compression.SnappyCompressor;
+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.data.gemfire.GemfireUtils;
+import org.springframework.data.gemfire.LocalRegionFactoryBean;
+import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
+import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
+import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
+import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
+import org.springframework.data.gemfire.test.model.Person;
+
+/**
+ * The EnableCompressionConfigurationUnitTests class...
+ *
+ * @author John Blum
+ * @since 1.0.0
+ */
+public class EnableCompressionConfigurationUnitTests {
+
+ private ConfigurableApplicationContext applicationContext;
+
+ @After
+ public void tearDown() {
+ Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close);
+ }
+
+ private ConfigurableApplicationContext newApplicationContext(Class>... annotatedClasses) {
+ return new AnnotationConfigApplicationContext(annotatedClasses);
+ }
+
+ private void assertRegionCompressor(Region, ?> region, String regionName, Compressor compressor) {
+
+ assertThat(region).isNotNull();
+ assertThat(region.getName()).isEqualTo(regionName);
+ assertThat(region.getFullPath()).isEqualTo(GemfireUtils.toRegionPath(regionName));
+ assertThat(region.getAttributes()).isNotNull();
+ assertThat(region.getAttributes().getCompressor()).isEqualTo(compressor);
+ }
+
+ @Test
+ public void enableCompressionForAllRegions() {
+
+ this.applicationContext = newApplicationContext(EnableCompressionForAllRegionsConfiguration.class);
+
+ assertThat(this.applicationContext).isNotNull();
+
+ Compressor compressor = this.applicationContext.getBean(Compressor.class);
+
+ assertThat(compressor).isInstanceOf(SnappyCompressor.class);
+
+ Arrays.asList("People", "ExampleLocalRegion", "ExamplePartitionRegion", "ExampleReplicateRegion")
+ .forEach(regionName -> {
+ assertThat(this.applicationContext.containsBean(regionName)).isTrue();
+ assertRegionCompressor(this.applicationContext.getBean(regionName, Region.class),
+ regionName, compressor);
+ });
+ }
+
+ @Test
+ public void enableCompressionForSelectRegions() {
+
+ this.applicationContext = newApplicationContext(EnableCompressionForSelectRegionsConfiguration.class);
+
+ assertThat(this.applicationContext).isNotNull();
+
+ Compressor compressor = this.applicationContext.getBean("MockCompressor", Compressor.class);
+
+ assertThat(compressor).isNotNull();
+ assertThat(this.applicationContext.containsBean(SNAPPY_COMPRESSOR_BEAN_NAME)).isTrue();
+
+ Arrays.asList("People", "ExampleClientRegion").forEach(regionName -> {
+ assertThat(this.applicationContext.containsBean(regionName)).isTrue();
+ assertRegionCompressor(this.applicationContext.getBean(regionName, Region.class),
+ regionName, "People".equals(regionName) ? compressor : null);
+ });
+ }
+
+ @PeerCacheApplication
+ @EnableGemFireMockObjects
+ @EnableEntityDefinedRegions(basePackageClasses = Person.class)
+ @EnableCompression
+ @SuppressWarnings("unused")
+ static class EnableCompressionForAllRegionsConfiguration {
+
+ @Bean("ExampleLocalRegion")
+ public LocalRegionFactoryBean