SGF-528 - Enable GemfireCacheManager to explicitly specify Cache names referring to Regions that will be used in Spring's Caching Infrastructure.
(cherry picked from commit 1af7ad523ae701ccd3e4770695ce1dcc7b5e12ef) Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
150
build.gradle
150
build.gradle
@@ -4,9 +4,11 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'io.spring.gradle:docbook-reference-plugin:0.3.0'
|
||||
classpath 'io.spring.gradle:spring-io-plugin:0.0.4.RELEASE'
|
||||
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.0'
|
||||
classpath 'org.asciidoctor:asciidoctorj:1.5.0'
|
||||
classpath 'org.springframework.build.gradle:bundlor-plugin:0.1.2'
|
||||
classpath 'org.springframework.build.gradle:bundlor-plugin:0.1.3'
|
||||
classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.6'
|
||||
classpath 'io.spring.gradle:docbook-reference-plugin:0.3.0'
|
||||
classpath 'io.spring.gradle:spring-io-plugin:0.0.4.RELEASE'
|
||||
@@ -33,6 +35,17 @@ archivesBaseName = project.name
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
output.classesDir = 'build/classes/main'
|
||||
output.resourcesDir = 'build/classes/main'
|
||||
}
|
||||
test {
|
||||
output.classesDir = 'build/classes/test'
|
||||
output.resourcesDir = 'build/classes/test'
|
||||
}
|
||||
}
|
||||
|
||||
[compileJava, compileTestJava]*.options*.compilerArgs = ["-Xlint:-serial"]
|
||||
|
||||
if (project.hasProperty('platformVersion')) {
|
||||
@@ -68,17 +81,6 @@ tasks.withType(Test).all {
|
||||
systemProperties['spring.profiles.active'] = 'apache-geode'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
output.resourcesDir = 'build/classes/main'
|
||||
output.classesDir = 'build/classes/main'
|
||||
}
|
||||
test {
|
||||
output.resourcesDir = 'build/classes/test'
|
||||
output.classesDir = 'build/classes/test'
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/libs-release" }
|
||||
maven { url "https://repo.spring.io/plugins-release"}
|
||||
@@ -121,13 +123,13 @@ dependencies {
|
||||
testCompile("org.springframework:spring-test:$springVersion") {
|
||||
exclude group: "commons-logging", module: "commons-logging"
|
||||
}
|
||||
testCompile "org.assertj:assertj-core:$assertjVersion"
|
||||
testCompile "junit:junit:$junitVersion"
|
||||
testCompile "org.apache.openwebbeans.test:cditest-owb:$openwebbeansVersion"
|
||||
testCompile "org.assertj:assertj-core:$assertjVersion"
|
||||
testCompile "org.hamcrest:hamcrest-core:$hamcrestVersion"
|
||||
testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
|
||||
testCompile "org.mockito:mockito-core:$mockitoVersion"
|
||||
testCompile "edu.umd.cs.mtc:multithreadedtc:$multiThreadedtcVersion"
|
||||
testCompile "org.apache.openwebbeans.test:cditest-owb:$openwebbeansVersion"
|
||||
|
||||
testRuntime "javax.el:el-api:$cdiVersion"
|
||||
testRuntime "javax.servlet:servlet-api:$servletApiVersion"
|
||||
@@ -159,33 +161,42 @@ jar {
|
||||
}
|
||||
}
|
||||
|
||||
javadoc {
|
||||
dependsOn = [ 'extractSharedResources' ]
|
||||
destinationDir = file("${buildDir}/api")
|
||||
ext.srcDir = file("$buildDir/shared-resources")
|
||||
ext.tmpDir = file("${buildDir}/api-work")
|
||||
|
||||
configure(options) {
|
||||
stylesheetFile = file("$buildDir/shared-resources/javadoc/spring-javadoc.css")
|
||||
docFilesSubDirs = true
|
||||
outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
|
||||
breakIterator = true
|
||||
showFromProtected()
|
||||
groups = [
|
||||
'Spring GemFire' : ['org.springframework.data.gemfire*'],
|
||||
]
|
||||
|
||||
links = [
|
||||
"http://docs.oracle.com/javase/6/docs/api/",
|
||||
"http://docs.spring.io/spring/docs/current/javadoc-api/",
|
||||
"http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/",
|
||||
"http://logging.apache.org/log4j/1.2/apidocs/",
|
||||
]
|
||||
|
||||
exclude "org/springframework/data/gemfire/config/**"
|
||||
task extractSharedResources(type: Copy) {
|
||||
from {
|
||||
// use of closure defers evaluation until execution time
|
||||
configurations.sharedResources.collect { zipTree(it) }
|
||||
}
|
||||
into "$buildDir/shared-resources"
|
||||
}
|
||||
|
||||
title = "${rootProject.description} ${version} API"
|
||||
javadoc {
|
||||
dependsOn = [ 'extractSharedResources' ]
|
||||
|
||||
destinationDir = file("${buildDir}/api")
|
||||
ext.tmpDir = file("${buildDir}/api-work")
|
||||
|
||||
configure(options) {
|
||||
breakIterator = true
|
||||
docFilesSubDirs = true
|
||||
outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
|
||||
stylesheetFile = file("$buildDir/shared-resources/javadoc/spring-javadoc.css")
|
||||
showFromProtected()
|
||||
|
||||
groups = [
|
||||
'Spring GemFire' : ['org.springframework.data.gemfire*'],
|
||||
]
|
||||
|
||||
links = [
|
||||
"http://docs.oracle.com/javase/6/docs/api/",
|
||||
"http://docs.spring.io/spring/docs/current/javadoc-api/",
|
||||
"http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/",
|
||||
"http://logging.apache.org/log4j/1.2/apidocs/",
|
||||
]
|
||||
|
||||
exclude "org/springframework/data/gemfire/config/**"
|
||||
}
|
||||
|
||||
title = "${rootProject.description} ${version} API"
|
||||
}
|
||||
|
||||
asciidoctor {
|
||||
@@ -233,6 +244,31 @@ task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
from javadoc
|
||||
}
|
||||
|
||||
task docsZip(type: Zip) {
|
||||
group = 'Distribution'
|
||||
classifier = 'docs'
|
||||
description = "Builds -${classifier} archive containing api and reference for deployment"
|
||||
dependsOn = [ 'javadoc', 'asciidoctor', 'referencePdf' ]
|
||||
|
||||
from('docs/src/info') {
|
||||
include 'changelog.txt'
|
||||
}
|
||||
|
||||
from (javadoc) {
|
||||
into 'api'
|
||||
}
|
||||
|
||||
from (asciidoctor.outputDir) {
|
||||
include "index.html"
|
||||
include "spring.css"
|
||||
into 'reference/html'
|
||||
}
|
||||
|
||||
from (referencePdf.outputDir) {
|
||||
into 'reference'
|
||||
}
|
||||
}
|
||||
|
||||
task schemaZip(type: Zip) {
|
||||
description = "Builds -${classifier} archive containing all XSDs for deployment"
|
||||
baseName = project.archivesBaseName
|
||||
@@ -264,32 +300,7 @@ task schemaZip(type: Zip) {
|
||||
}
|
||||
}
|
||||
|
||||
task docsZip(type: Zip, dependsOn: [javadoc, asciidoctor, referencePdf]) {
|
||||
description = "Builds -${classifier} archive containing api and reference for deployment"
|
||||
baseName = project.archivesBaseName
|
||||
classifier = 'docs'
|
||||
group = 'Distribution'
|
||||
|
||||
from('src/main/resources') {
|
||||
include 'changelog.txt'
|
||||
}
|
||||
|
||||
from (javadoc) {
|
||||
into 'api'
|
||||
}
|
||||
|
||||
from (asciidoctor.outputDir) {
|
||||
include "index.html"
|
||||
include "spring.css"
|
||||
into 'reference/html'
|
||||
}
|
||||
|
||||
from (referencePdf.outputDir) {
|
||||
into 'reference'
|
||||
}
|
||||
}
|
||||
|
||||
task distZip(type: Zip, dependsOn: [jar, sourcesJar, javadocJar, schemaZip, docsZip]) {
|
||||
task distZip(type: Zip, dependsOn: [jar, docsZip, schemaZip, sourcesJar, javadocJar]) {
|
||||
description = "Builds -${classifier} archive, containing all jars and docs, suitable for community download page."
|
||||
|
||||
baseName = project.archivesBaseName
|
||||
@@ -300,6 +311,7 @@ task distZip(type: Zip, dependsOn: [jar, sourcesJar, javadocJar, schemaZip, docs
|
||||
|
||||
into (zipRootDir) {
|
||||
from('src/main/resources') {
|
||||
include 'changelog.txt'
|
||||
include 'license.txt'
|
||||
include 'notice.txt'
|
||||
include 'readme.txt'
|
||||
@@ -328,14 +340,6 @@ task distZip(type: Zip, dependsOn: [jar, sourcesJar, javadocJar, schemaZip, docs
|
||||
}
|
||||
}
|
||||
|
||||
task extractSharedResources(type: Copy) {
|
||||
from { // use of closure defers evaluation until execution time
|
||||
configurations.sharedResources.collect { zipTree(it) }
|
||||
}
|
||||
|
||||
into "$buildDir/shared-resources"
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourcesJar
|
||||
archives javadocJar
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
antlrVersion=2.7.7
|
||||
aspectjVersion=1.8.9
|
||||
assertjVersion=3.5.2
|
||||
assertjVersion=2.5.0
|
||||
cdiVersion=1.0
|
||||
gemfireVersion=1.0.0-incubating.M3
|
||||
googleCodeFindbugsVersion=2.0.2
|
||||
@@ -13,8 +13,8 @@ multiThreadedtcVersion=1.01
|
||||
openwebbeansVersion=1.2.8
|
||||
servletApiVersion=2.5
|
||||
slf4jVersion=1.7.21
|
||||
springVersion=4.2.8.RELEASE
|
||||
spring.range="[4.0.0, 5.0.0)"
|
||||
springVersion=4.3.3.RELEASE
|
||||
springDataBuildVersion=1.8.3.RELEASE
|
||||
springDataCommonsVersion=1.12.3.RELEASE
|
||||
springShellVersion=1.1.0.RELEASE
|
||||
|
||||
16
pom.xml
16
pom.xml
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>1.8.3.RELEASE</version>
|
||||
<version>1.9.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
@@ -20,7 +20,7 @@
|
||||
<properties>
|
||||
<dist.key>SGF</dist.key>
|
||||
<antlr.version>2.7.7</antlr.version>
|
||||
<assertj.version>3.5.2</assertj.version>
|
||||
<assertj.version>2.5.0</assertj.version>
|
||||
<gemfire.version>1.0.0-incubating.M3</gemfire.version>
|
||||
<google-code-findbugs.version>2.0.2</google-code-findbugs.version>
|
||||
<multithreadedtc.version>1.01</multithreadedtc.version>
|
||||
@@ -169,16 +169,16 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>${webbeans}</version>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbyLocale_zh_TW</artifactId>
|
||||
<version>10.9.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbyLocale_zh_TW</artifactId>
|
||||
<version>10.9.1.0</version>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -18,18 +18,16 @@ package org.springframework.data.gemfire.support;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.GemFireCache;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Spring Framework {@link Cache} implementation backed by a GemFire {@link Region}.
|
||||
*
|
||||
* Supports GemFire 6.5 or higher.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @author Oliver Gierke
|
||||
@@ -38,58 +36,133 @@ import com.gemstone.gemfire.cache.Region;
|
||||
*/
|
||||
public class GemfireCache implements Cache {
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
private final Region region;
|
||||
|
||||
/**
|
||||
* Creates a {@link GemFireCache} instance.
|
||||
*
|
||||
* @param region backing GemFire region
|
||||
* Wraps a GemFire {@link Region} in an instance of {@link GemfireCache} to adapt the GemFire {@link Region}
|
||||
* to function as a Spring {@link Cache} in Spring's caching infrastructure.
|
||||
*
|
||||
* @param region GemFire {@link Region} to wrap.
|
||||
* @return an instance of {@link GemfireCache} backed by the provided GemFire {@link Region}.
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
* @see org.springframework.cache.Cache
|
||||
* @see #GemfireCache(Region)
|
||||
*/
|
||||
public GemfireCache(final Region<?, ?> region) {
|
||||
public static GemfireCache wrap(Region<?, ?> region) {
|
||||
return new GemfireCache(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link GemFireCache} initialized with the given GemFire {@link Region}.
|
||||
* The {@link Region} will function as the backing store and implementation for
|
||||
* the Spring {@link Cache} interface.
|
||||
*
|
||||
* @param region GemFire {@link Region} backing the Spring {@link Cache}.
|
||||
* @throws IllegalArgumentException if {@link Region} is null.
|
||||
*/
|
||||
public GemfireCache(Region<?, ?> region) {
|
||||
Assert.notNull(region, "GemFire Region must not be null");
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GemFire {@link Region} used as the implementation for this Spring {@link Cache}.
|
||||
*
|
||||
* @return the GemFire {@link Region} used as the implementation for this Spring {@link Cache}.
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
public Region getNativeCache() {
|
||||
return this.region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this Spring {@link Cache}.
|
||||
*
|
||||
* @return the name of this Spring {@link Cache}.
|
||||
* @see com.gemstone.gemfire.cache.Region#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return region.getName();
|
||||
}
|
||||
|
||||
public Region<?, ?> getNativeCache() {
|
||||
return region;
|
||||
return getNativeCache().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the entire contents of this Spring {@link Cache}.
|
||||
*
|
||||
* @see com.gemstone.gemfire.cache.Region#clear()
|
||||
*/
|
||||
public void clear() {
|
||||
region.clear();
|
||||
getNativeCache().clear();
|
||||
}
|
||||
|
||||
public void evict(final Object key) {
|
||||
region.destroy(key);
|
||||
/**
|
||||
* Evicts (destroys) the entry (key/value) mapped to the given key from this Spring {@link Cache}.
|
||||
*
|
||||
* @param key key used to identify the cache entry to evict.
|
||||
* @see com.gemstone.gemfire.cache.Region#destroy(Object)
|
||||
*/
|
||||
public void evict(Object key) {
|
||||
getNativeCache().destroy(key);
|
||||
}
|
||||
|
||||
public ValueWrapper get(final Object key) {
|
||||
Object value = region.get(key);
|
||||
/**
|
||||
* Returns the cache value for the given key wrapped in an instance of
|
||||
* {@link org.springframework.cache.Cache.ValueWrapper}.
|
||||
*
|
||||
* @param key key identifying the the value to retrieve from the cache.
|
||||
* @return the value cached with the given key.
|
||||
* @see org.springframework.cache.Cache.ValueWrapper
|
||||
* @see com.gemstone.gemfire.cache.Region#get(Object)
|
||||
*/
|
||||
public ValueWrapper get(Object key) {
|
||||
Object value = getNativeCache().get(key);
|
||||
|
||||
return (value == null ? null : new SimpleValueWrapper(value));
|
||||
return (value != null ? new SimpleValueWrapper(value) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache value for the given key cast to the specified {@link Class} type.
|
||||
*
|
||||
* @param <T> desired {@link Class} type of the cache value.
|
||||
* @param key key identifying the the value to retrieve from the cache.
|
||||
* @param type desired {@link Class} type of the value.
|
||||
* @return the cache value for the given key cast to the specified {@link Class} type.
|
||||
* @throws IllegalStateException if the value is not null and not an instance of the desired type.
|
||||
* @see com.gemstone.gemfire.cache.Region#get(Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(final Object key, final Class<T> type) {
|
||||
Object value = region.get(key);
|
||||
public <T> T get(Object key, Class<T> type) {
|
||||
Object value = getNativeCache().get(key);
|
||||
|
||||
if (value != null && type != null && !type.isInstance(value)) {
|
||||
throw new IllegalStateException(String.format("Cached value is not of required type [%1$s]: %2$s",
|
||||
type.getName(), value));
|
||||
throw new IllegalStateException(String.format(
|
||||
"Cached value [%1$s] is not an instance of type [%2$s]",
|
||||
value, type.getName()));
|
||||
}
|
||||
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache value for given key. If the value is {@literal null}, then the provided
|
||||
* {@link Callable} {@code valueLoader} will be called to obtain a value and add the entry
|
||||
* to this cache.
|
||||
*
|
||||
* @param <T> {@link Class} type of the value.
|
||||
* @param key key identifying the the value to retrieve from the cache.
|
||||
* @param valueLoader {@link Callable} object used to load a value if the entry identified by the key
|
||||
* does not already have value.
|
||||
* @return the cache value of the given key or a value obtained by calling the {@link Callable} object
|
||||
* if the value for key is {@literal null}.
|
||||
* @throws org.springframework.cache.Cache.ValueRetrievalException if an error occurs while trying to
|
||||
* load a value for given key using the {@link Callable}.
|
||||
* @see #get(Object, Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(final Object key, final Callable<T> valueLoader) {
|
||||
public <T> T get(Object key, Callable<T> valueLoader) {
|
||||
T value = (T) get(key, Object.class);
|
||||
|
||||
if (value == null) {
|
||||
synchronized (region) {
|
||||
synchronized (getNativeCache()) {
|
||||
value = (T) get(key, Object.class);
|
||||
|
||||
if (value == null) {
|
||||
@@ -98,11 +171,7 @@ public class GemfireCache implements Cache {
|
||||
put(key, value);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(String.format(
|
||||
"Failed to load value for key [%1$s] using valueLoader [%2$s]", key,
|
||||
ObjectUtils.nullSafeClassName(valueLoader)));
|
||||
//TODO throw ValueRetrievalException when SDG is based on Spring Framework 4.3
|
||||
//throw new ValueRetrievalException(key, valueLoader, e);
|
||||
throw new ValueRetrievalException(key, valueLoader, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,24 +180,34 @@ public class GemfireCache implements Cache {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given value in the cache referenced by the given key. This operation will only store the value
|
||||
* if the value is not {@literal null}.
|
||||
*
|
||||
* @param key key used to reference the value in the cache.
|
||||
* @param value value to store in the cache referenced by the key.
|
||||
* @see com.gemstone.gemfire.cache.Region#put(Object, Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void put(final Object key, final Object value) {
|
||||
public void put(Object key, Object value) {
|
||||
if (value != null) {
|
||||
region.put(key, value);
|
||||
getNativeCache().put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation to satisfy extension of the {@link Cache} interface in Spring 4.1. Don't add the {@link Override}
|
||||
* annotation as this will break the compilation on 4.0.
|
||||
*
|
||||
* Implementation of {@link Cache#putIfAbsent(Object, Object)} satisfying the extension of
|
||||
* the {@link Cache} interface in Spring 4.1. Don't add the {@link Override} annotation
|
||||
* otherwise this will break the compilation on 4.0.
|
||||
*
|
||||
* @return the existing value if the given key is already mapped to a value.
|
||||
* @see org.springframework.cache.Cache#putIfAbsent(java.lang.Object, java.lang.Object)
|
||||
* @see com.gemstone.gemfire.cache.Region#putIfAbsent(Object, Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ValueWrapper putIfAbsent(Object key, Object value) {
|
||||
Object existingValue = region.putIfAbsent(key, value);
|
||||
Object existingValue = getNativeCache().putIfAbsent(key, value);
|
||||
|
||||
return (existingValue == null ? null : new SimpleValueWrapper(existingValue));
|
||||
return (existingValue != null ? new SimpleValueWrapper(existingValue) : null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,103 +17,223 @@
|
||||
package org.springframework.data.gemfire.support;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.gemstone.gemfire.cache.GemFireCache;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.support.AbstractCacheManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
/**
|
||||
* Spring Framework {@link CacheManager} backed by a Gemfire {@link com.gemstone.gemfire.cache.Cache}. Automatically
|
||||
* discovers the created caches (or {@link Region}s in Gemfire terminology).
|
||||
*
|
||||
* Core Spring Framework {@link CacheManager} implementation backed by a GemFire cache instance
|
||||
* (either a client or peer cache).
|
||||
*
|
||||
* Automatically discovers available caches (or GemFire {@link Region Regions}) when a cache for a given name
|
||||
* is missing and dynamic cache lookup/creation is enabled.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see org.springframework.cache.Cache
|
||||
* @see org.springframework.cache.CacheManager
|
||||
* @see org.springframework.cache.support.AbstractCacheManager
|
||||
* @see com.gemstone.gemfire.cache.Cache
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class GemfireCacheManager extends AbstractCacheManager {
|
||||
|
||||
private com.gemstone.gemfire.cache.Cache gemfireCache;
|
||||
private final AtomicBoolean dynamic = new AtomicBoolean(true);
|
||||
|
||||
private Set<Region<?,?>> regions;
|
||||
private com.gemstone.gemfire.cache.GemFireCache gemfireCache;
|
||||
|
||||
private Set<Region<?, ?>> regions;
|
||||
|
||||
private Set<String> cacheNames;
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
<T extends GemFireCache> T assertGemFireCacheAvailable(T gemfireCache) {
|
||||
Assert.state(gemfireCache != null, "A GemFire cache instance is required");
|
||||
Assert.state(!gemfireCache.isClosed(), String.format("GemFire cache [%s] has been closed",
|
||||
gemfireCache.getName()));
|
||||
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
Region<?, ?> assertGemFireRegionAvailable(Region<?, ?> region, String cacheName) {
|
||||
Assert.state(region != null, String.format("No Region for cache name [%s] was found", cacheName));
|
||||
Assert.state(!region.isDestroyed(), String.format("Region [%s] has been destroyed", cacheName));
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the GemFire Cache Regions managed by this CacheManager.
|
||||
* Loads all configured GemFire {@link Region Regions} that will be used by this {@link CacheManager}.
|
||||
*
|
||||
* @return a Collection of GemFire Cache Regions (caches) to be managed by this SDG CacheManager.
|
||||
* Any GemFire {@link Region Regions} configured with the {@link #regions} property will take precedence over
|
||||
* any configured {@link #cacheNames}. If no GemFire {@link Region Regions} were configured, then any
|
||||
* {@link #cacheNames} that were specified will be used to lookup existing GemFire {@link Region Regions}
|
||||
* to function as Spring {@link Cache Caches}in Spring's caching infrastructure.
|
||||
*
|
||||
* However, if neither {@link #regions} nor {@link #cacheNames} were specified, then all defined GemFire
|
||||
* {@link Region Regions} declared in the Spring application context, as determined by
|
||||
* {@link GemFireCache#rootRegions()}, will be used as Spring {@link Cache Caches}, and this {@link CacheManager}
|
||||
* will allow any dynamically created GemFire {@link Region Regions} at runtime to be found and used as a
|
||||
* Spring {@link Cache} as well.
|
||||
*
|
||||
* @return a {@link Collection} of GemFire {@link Region Regions} used by this {@link CacheManager}
|
||||
* to function as {@link Cache Caches} in Spring's caching infrastructure.
|
||||
* @throws IllegalStateException if a GemFire cache instance was not provided, the provided GemFire cache instance
|
||||
* has been closed, no GemFire {@link Region} could be found for a given cache name, or the GemFire {@link Region}
|
||||
* for the given cache name has been destroyed.
|
||||
* @see org.springframework.cache.Cache
|
||||
* @see com.gemstone.gemfire.cache.Cache#rootRegions()
|
||||
*/
|
||||
@Override
|
||||
protected Collection<Cache> loadCaches() {
|
||||
if (regions == null) {
|
||||
Assert.state(gemfireCache != null, "A backing GemFire Cache is required.");
|
||||
Assert.state(!gemfireCache.isClosed(), "The GemFire Cache is closed; an open instance is required.");
|
||||
Set<Region<?, ?>> regions = resolveRegions(this.gemfireCache, this.regions, this.cacheNames);
|
||||
|
||||
regions = gemfireCache.rootRegions();
|
||||
}
|
||||
Collection<Cache> caches = new HashSet<Cache>(regions.size());
|
||||
|
||||
Collection<Cache> caches = new LinkedHashSet<Cache>(regions.size());
|
||||
|
||||
for (Region<?,?> region: this.regions) {
|
||||
caches.add(new GemfireCache(region));
|
||||
for (Region<?, ?> region : regions) {
|
||||
caches.add(GemfireCache.wrap(region));
|
||||
}
|
||||
|
||||
return caches;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Set<Region<?, ?>> resolveRegions(GemFireCache gemfireCache, Set<Region<?, ?>> regions, Set<String> cacheNames) {
|
||||
if (isSet(regions)) {
|
||||
dynamic.set(false);
|
||||
return regions;
|
||||
}
|
||||
else if (isSet(cacheNames)) {
|
||||
dynamic.set(false);
|
||||
|
||||
regions = new HashSet<Region<?, ?>>(cacheNames.size());
|
||||
|
||||
for (String cacheName : cacheNames) {
|
||||
regions.add(regionFor(gemfireCache, cacheName));
|
||||
}
|
||||
|
||||
return regions;
|
||||
}
|
||||
else {
|
||||
return assertGemFireCacheAvailable(gemfireCache).rootRegions();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
boolean isSet(Iterable<?> collection) {
|
||||
return (collection != null && collection.iterator().hasNext());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Region<?, ?> regionFor(GemFireCache gemfireCache, String cacheName) {
|
||||
return assertGemFireRegionAvailable(assertGemFireCacheAvailable(gemfireCache).getRegion(cacheName), cacheName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Cache (GemFire Cache Region) by name.
|
||||
* Returns a missing Spring {@link Cache} for the given {@code name}.
|
||||
*
|
||||
* @param name a String indicating the name of the Cache to get.
|
||||
* @return a Cache with the given name.
|
||||
* To return a missing Spring {@link Cache} for the given {@code name}, dynamic cache lookup/creation must be
|
||||
* enabled, which means that either the {@link #cacheNames} or {@link #regions} properties must not be set.
|
||||
* If either property was specified then dynamic Spring {@link Cache} lookup/creation will be disabled and this
|
||||
* overridden {@link AbstractCacheManager#getMissingCache(String)} method will return {@literal null}.
|
||||
*
|
||||
* @param name name of the missing Spring {@link Cache} to lookup (and potentially create).
|
||||
* @return a Spring {@link Cache} instance for the given {@code name} or {@literal null} if the {@link Cache}
|
||||
* cannot be found (or possibly created).
|
||||
* @see org.springframework.cache.support.AbstractCacheManager#getMissingCache(String)
|
||||
* @see org.springframework.cache.Cache
|
||||
*/
|
||||
@Override
|
||||
public Cache getCache(String name) {
|
||||
Cache cache = super.getCache(name);
|
||||
protected Cache getMissingCache(String name) {
|
||||
Cache cache = super.getMissingCache(name);
|
||||
|
||||
if (cache == null) {
|
||||
// check the GemFire Cache again in case the Cache (Region) was added at runtime
|
||||
Region<?, ?> region = gemfireCache.getRegion(name);
|
||||
|
||||
if (region != null) {
|
||||
cache = new GemfireCache(region);
|
||||
addCache(cache);
|
||||
}
|
||||
}
|
||||
|
||||
return cache;
|
||||
return (cache != null ? cache : (isDynamic() ? GemfireCache.wrap(regionFor(this.gemfireCache, name)) : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GemFire Cache backing this {@link CacheManager}.
|
||||
*
|
||||
* @param gemfireCache the GemFire Peer Cache instance.
|
||||
* @see com.gemstone.gemfire.cache.Cache
|
||||
* Determines whether this {@link CacheManager} allows the dynamic creation of a {@link Cache} at runtime.
|
||||
*
|
||||
* @return a boolean value indicating whether dynamic {@link Cache} creation is enabled.
|
||||
*/
|
||||
public void setCache(com.gemstone.gemfire.cache.Cache gemfireCache) {
|
||||
protected boolean isDynamic() {
|
||||
return dynamic.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GemFire cache instance backing this {@link CacheManager}.
|
||||
*
|
||||
* When set, if neither {@link Region Regions} nor {@code cacheNames} were specified, then this {@link CacheManager}
|
||||
* is capable of creating Spring {@link Cache Caches} backed by existing GemFire {@link Region Regions} used by
|
||||
* the application at runtime. However, in order to dynamically create Spring {@link Cache Caches} a reference to
|
||||
* an open GemFire cache instance must be set.
|
||||
*
|
||||
* @param gemfireCache the GemFire cache instance used by this {@link CacheManager}
|
||||
* to manage Spring {@link Cache Caches}.
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
*/
|
||||
public void setCache(com.gemstone.gemfire.cache.GemFireCache gemfireCache) {
|
||||
this.gemfireCache = gemfireCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the Regions to use (alternative to injecting the GemFire Cache).
|
||||
* Returns the {@link GemFireCache} instance backing this {@link CacheManager}.
|
||||
*
|
||||
* @param regions the Set of Regions (caches) managed by this CacheManager.
|
||||
* @return the {@link GemFireCache} instance backing this {@link CacheManager}.
|
||||
* @see com.gemstone.gemfire.cache.GemFireCache
|
||||
*/
|
||||
protected com.gemstone.gemfire.cache.GemFireCache getCache() {
|
||||
return this.gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the names of all Spring {@link Cache Caches} that will be used in the application.
|
||||
*
|
||||
* When set, this disables the dynamic capability of this {@link CacheManager} to create Spring {@link Cache Caches}
|
||||
* at runtime by dynamically looking up existing {@link Region Regions} from the GemFire cache instance.
|
||||
*
|
||||
* @param cacheNames {@link Set} of cache names that will be used in the application.
|
||||
* @see java.util.Set
|
||||
*/
|
||||
public void setCacheNames(Set<String> cacheNames) {
|
||||
this.cacheNames = cacheNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly sets the GemFire {@link Region Regions} to be used as Spring {@link Cache Caches}
|
||||
* in the application.
|
||||
*
|
||||
* When set, this disables the dynamic capability of this {@link CacheManager} to create Spring {@link Cache Caches}
|
||||
* at runtime by dynamically looking up existing {@link Region Regions} from the GemFire cache instance.
|
||||
*
|
||||
* @param regions {@link Set} of GemFire {@link Region Regions} used by this {@link CacheManager}
|
||||
* as Spring {@link Cache Caches}.
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
public void setRegions(Set<Region<?,?>> regions) {
|
||||
public void setRegions(Set<Region<?, ?>> regions) {
|
||||
this.regions = regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of GemFire {@link Region Regions} used explicitly as Spring {@link Cache Caches}
|
||||
* in Spring's caching infrastructure.
|
||||
*
|
||||
* @return the set of GemFire {@link Region Regions} functioning as Spring {@link Cache Caches}
|
||||
* in Spring's caching infrastructure
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
protected Set<Region<?, ?>> getRegions() {
|
||||
return this.regions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 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 static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cache.Cache;
|
||||
|
||||
/**
|
||||
* Abstract base test class for native cache implementations.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.springframework.cache.Cache
|
||||
*/
|
||||
public abstract class AbstractNativeCacheTest<T> {
|
||||
|
||||
protected static final String CACHE_NAME = "Example";
|
||||
|
||||
private T nativeCache;
|
||||
private Cache cache;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
nativeCache = createNativeCache();
|
||||
cache = createCache(nativeCache);
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <C extends Cache> C createCache() throws Exception {
|
||||
return (C) createCache(createNativeCache());
|
||||
}
|
||||
|
||||
protected abstract Cache createCache(T nativeCache);
|
||||
|
||||
protected abstract T createNativeCache() throws Exception;
|
||||
|
||||
@Test
|
||||
public void cacheNameIsEqualToExpected() throws Exception {
|
||||
assertThat(cache.getName(), is(equalTo(CACHE_NAME)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void nativeCacheIsSameAsExpected() throws Exception {
|
||||
assertThat((T) cache.getNativeCache(), is(sameInstance(nativeCache)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cachePutIsSuccessful() throws Exception {
|
||||
assertThat(cache.get("enescu"), is(nullValue()));
|
||||
cache.put("enescu", "george");
|
||||
assertThat(String.valueOf(cache.get("enescu").get()), is(equalTo("george")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheGetForClassTypeIsSuccessful() {
|
||||
cache.put("one", Boolean.TRUE);
|
||||
cache.put("two", 'X');
|
||||
cache.put("three", 101);
|
||||
cache.put("four", Math.PI);
|
||||
cache.put("five", "TEST");
|
||||
|
||||
assertThat(cache.get("one", Boolean.class), is(equalTo(Boolean.TRUE)));
|
||||
assertThat(cache.get("two", Character.class), is(equalTo('X')));
|
||||
assertThat(cache.get("three", Integer.class), is(equalTo(101)));
|
||||
assertThat(cache.get("four", Double.class), is(equalTo(Math.PI)));
|
||||
assertThat(cache.get("five", String.class), is(equalTo("TEST")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheClearIsSuccessful() throws Exception {
|
||||
assertThat(cache.get("enescu"), is(nullValue()));
|
||||
|
||||
cache.put("enescu", "george");
|
||||
|
||||
assertThat(cache.get("vlaicu"), is(nullValue()));
|
||||
|
||||
cache.put("vlaicu", "aurel");
|
||||
|
||||
assertThat(cache.get("enescu", String.class), is(equalTo("george")));
|
||||
assertThat(cache.get("vlaicu", String.class), is(equalTo("aurel")));
|
||||
|
||||
cache.clear();
|
||||
|
||||
assertThat(cache.get("vlaicu"), is(nullValue()));
|
||||
assertThat(cache.get("enescu"), is(nullValue()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2010 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 static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cache.Cache;
|
||||
|
||||
/**
|
||||
* Abstract base test class for native cache implementations.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.cache.Cache
|
||||
*/
|
||||
public abstract class AbstractNativeCacheTests<T> {
|
||||
|
||||
protected static final String CACHE_NAME = "Example";
|
||||
|
||||
private T nativeCache;
|
||||
private Cache cache;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
nativeCache = newNativeCache();
|
||||
cache = newCache(nativeCache);
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <C extends Cache> C newCache() throws Exception {
|
||||
return (C) newCache(newNativeCache());
|
||||
}
|
||||
|
||||
protected abstract Cache newCache(T nativeCache);
|
||||
|
||||
protected abstract T newNativeCache() throws Exception;
|
||||
|
||||
@Test
|
||||
public void cacheNameIsEqualToExpected() throws Exception {
|
||||
assertThat(cache.getName()).isEqualTo(CACHE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nativeCacheIsSameAsExpected() throws Exception {
|
||||
assertThat(cache.getNativeCache()).isSameAs(nativeCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cachePutIsSuccessful() throws Exception {
|
||||
assertThat(cache.get("enescu")).isNull();
|
||||
|
||||
cache.put("enescu", "george");
|
||||
|
||||
assertThat(cache.get("enescu").get()).isEqualTo("george");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cachePutThenClearIsSuccessful() throws Exception {
|
||||
cache.put("enescu", "george");
|
||||
cache.put("vlaicu", "aurel");
|
||||
|
||||
assertThat(cache.get("enescu", String.class)).isEqualTo("george");
|
||||
assertThat(cache.get("vlaicu", String.class)).isEqualTo("aurel");
|
||||
|
||||
cache.clear();
|
||||
|
||||
assertThat(cache.get("vlaicu")).isNull();
|
||||
assertThat(cache.get("enescu")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cachePutThenGetForClassTypeIsSuccessful() {
|
||||
cache.put("one", Boolean.TRUE);
|
||||
cache.put("two", 'X');
|
||||
cache.put("three", 101);
|
||||
cache.put("four", Math.PI);
|
||||
cache.put("five", "TEST");
|
||||
|
||||
assertThat(cache.get("one", Boolean.class)).isTrue();
|
||||
assertThat(cache.get("two", Character.class)).isEqualTo('X');
|
||||
assertThat(cache.get("three", Integer.class)).isEqualTo(101);
|
||||
assertThat(cache.get("four", Double.class)).isEqualTo(Math.PI);
|
||||
assertThat(cache.get("five", String.class)).isEqualTo("TEST");
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,18 @@
|
||||
|
||||
package org.springframework.data.gemfire.support;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import edu.umd.cs.mtc.MultithreadedTestCase;
|
||||
import edu.umd.cs.mtc.TestFramework;
|
||||
|
||||
import com.gemstone.gemfire.cache.CacheFactory;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -30,42 +35,35 @@ import org.junit.rules.ExpectedException;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.data.gemfire.GemfireUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.CacheFactory;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import edu.umd.cs.mtc.MultithreadedTestCase;
|
||||
import edu.umd.cs.mtc.TestFramework;
|
||||
|
||||
/**
|
||||
* Tests the interaction between the Spring Framework Cache Abstraction and GemFire as a provider
|
||||
* using Spring Data GemFire's extension.
|
||||
* Integration Tests for {@link GemfireCache}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @author Oliver Gierke
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see edu.umd.cs.mtc.MultithreadedTestCase
|
||||
* @see edu.umd.cs.mtc.TestFramework
|
||||
* @see org.springframework.cache.Cache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Object>> {
|
||||
public class GemfireCacheIntegrationTests extends AbstractNativeCacheTests<Region<Object, Object>> {
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Override
|
||||
protected Cache createCache(Region<Object, Object> nativeCache) {
|
||||
protected Cache newCache(Region<Object, Object> nativeCache) {
|
||||
return new GemfireCache(nativeCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Region<Object, Object> createNativeCache() throws Exception {
|
||||
protected Region<Object, Object> newNativeCache() throws Exception {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", GemfireCacheTest.class.getName());
|
||||
gemfireProperties.setProperty("name", GemfireCacheIntegrationTests.class.getName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("locators", "");
|
||||
gemfireProperties.setProperty("log-level", "warning");
|
||||
|
||||
com.gemstone.gemfire.cache.Cache cache = GemfireUtils.getCache();
|
||||
@@ -84,11 +82,11 @@ public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Obj
|
||||
*/
|
||||
@Test
|
||||
public void findsTypedValue() throws Exception {
|
||||
Cache cache = createCache();
|
||||
Cache cache = newCache();
|
||||
|
||||
cache.put("key", "value");
|
||||
|
||||
assertThat(cache.get("key", String.class), is("value"));
|
||||
assertThat(cache.get("key", String.class)).isEqualTo("value");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,11 +94,11 @@ public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Obj
|
||||
*/
|
||||
@Test
|
||||
public void skipTypeChecksIfTargetTypeIsNull() throws Exception {
|
||||
Cache cache = createCache();
|
||||
Cache cache = newCache();
|
||||
|
||||
cache.put("key", "value");
|
||||
cache.put("key", 1);
|
||||
|
||||
assertThat(cache.get("key", (Class<String>) null), is("value"));
|
||||
assertThat(cache.get("key", (Class<?>) null)).isEqualTo(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,63 +106,67 @@ public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Obj
|
||||
*/
|
||||
@Test
|
||||
public void throwsIllegalStateExceptionIfTypedAccessDoesNotFindMatchingType() throws Exception {
|
||||
Cache cache = createCache();
|
||||
Cache cache = newCache();
|
||||
|
||||
cache.put("key", "value");
|
||||
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage(Integer.class.getName());
|
||||
expectedException.expectMessage("value");
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectMessage(Integer.class.getName());
|
||||
exception.expectMessage(String.format("Cached value [value] is not an instance of type [%s]",
|
||||
Integer.class.getName()));
|
||||
|
||||
cache.get("key", Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheGetWithValueLoaderFindsValue() throws Exception {
|
||||
GemfireCache cache = createCache();
|
||||
GemfireCache cache = newCache();
|
||||
|
||||
cache.put("key", "value");
|
||||
|
||||
assertThat(String.valueOf(cache.get("key", TestCacheLoader.NULL_VALUE)), is(equalTo("value")));
|
||||
assertThat(TestCacheLoader.NULL_VALUE.wasCalled(), is(false));
|
||||
assertThat(cache.get("key", TestValueLoader.NULL_VALUE)).isEqualTo("value");
|
||||
assertThat(TestValueLoader.NULL_VALUE.wasCalled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void cacheGetWithValueLoaderUsesValueLoader() throws Exception {
|
||||
GemfireCache cache = createCache();
|
||||
public void cacheGetWithValueLoaderUsesValueLoaderReturnsValue() throws Exception {
|
||||
GemfireCache cache = newCache();
|
||||
|
||||
TestCacheLoader<String> cacheLoader = new TestCacheLoader<String>("test");
|
||||
TestValueLoader<String> valueLoader = new TestValueLoader<String>("test");
|
||||
|
||||
assertThat(cache.get("key", cacheLoader), is(equalTo("test")));
|
||||
assertThat(cacheLoader.wasCalled(), is(true));
|
||||
assertThat(((Region<Object, String>) cache.getNativeCache()).get("key"), is(equalTo("test")));
|
||||
assertThat(cache.get("key", valueLoader)).isEqualTo("test");
|
||||
assertThat(valueLoader.wasCalled()).isTrue();
|
||||
assertThat(((Region<Object, String>) cache.getNativeCache()).get("key")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void cacheGetWithValueLoaderUsesValueLoaderReturningNull() throws Exception {
|
||||
GemfireCache cache = createCache();
|
||||
public void cacheGetWithValueLoaderUsesValueLoaderReturnsNull() throws Exception {
|
||||
GemfireCache cache = newCache();
|
||||
|
||||
assertThat(cache.get("key", TestCacheLoader.NULL_VALUE), is(nullValue()));
|
||||
assertThat(TestCacheLoader.NULL_VALUE.wasCalled(), is(true));
|
||||
assertThat(cache.getNativeCache().containsKey("key"), is(false));
|
||||
assertThat(cache.get("key", TestValueLoader.NULL_VALUE)).isNull();
|
||||
assertThat(TestValueLoader.NULL_VALUE.wasCalled()).isTrue();
|
||||
assertThat(cache.getNativeCache().containsKey("key")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void cacheGetWithValueLoaderUsesValueLoaderThrowingException() throws Exception {
|
||||
GemfireCache cache = createCache();
|
||||
public void cacheGetWithValueLoaderUsesValueLoaderAndThrowsException() throws Exception {
|
||||
GemfireCache cache = newCache();
|
||||
|
||||
TestCacheLoader<Exception> exceptionThrowingCacheLoader = new TestCacheLoader<Exception>(
|
||||
new IllegalStateException("test"));
|
||||
try {
|
||||
TestValueLoader<Exception> exceptionThrowingValueLoader = new TestValueLoader<Exception>(
|
||||
new IllegalStateException("test"));
|
||||
|
||||
expectedException.expect(RuntimeException.class);
|
||||
expectedException.expectCause(is(nullValue(IllegalStateException.class)));
|
||||
expectedException.expectMessage(String.format("Failed to load value for key [key] using valueLoader [%1$s]",
|
||||
exceptionThrowingCacheLoader.getClass().getName()));
|
||||
exception.expect(Cache.ValueRetrievalException.class);
|
||||
exception.expectCause(is(IllegalStateException.class));
|
||||
|
||||
cache.get("key", exceptionThrowingCacheLoader);
|
||||
cache.get("key", exceptionThrowingValueLoader);
|
||||
}
|
||||
finally {
|
||||
assertThat(cache.getNativeCache().containsKey("key")).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -177,15 +179,15 @@ public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Obj
|
||||
|
||||
private GemfireCache cache;
|
||||
|
||||
private TestCacheLoader<String> cacheLoader;
|
||||
private TestValueLoader<String> cacheLoader;
|
||||
|
||||
@Override
|
||||
public void initialize(){
|
||||
super.initialize();
|
||||
|
||||
cache = createCacheHandlesCheckedException();
|
||||
cache = newCacheHandlesCheckedException();
|
||||
|
||||
cacheLoader = new TestCacheLoader<String>("test") {
|
||||
cacheLoader = new TestValueLoader<String>("test") {
|
||||
@Override public String call() throws Exception {
|
||||
waitForTick(2);
|
||||
return super.call();
|
||||
@@ -193,12 +195,12 @@ public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Obj
|
||||
};
|
||||
}
|
||||
|
||||
<T extends Cache> T createCacheHandlesCheckedException() {
|
||||
<T extends Cache> T newCacheHandlesCheckedException() {
|
||||
try {
|
||||
return createCache();
|
||||
return newCache();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("failed to create Cache", e);
|
||||
throw new RuntimeException("Failed to create Cache", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,8 +212,8 @@ public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Obj
|
||||
String value = cache.get("key", cacheLoader);
|
||||
|
||||
assertTick(2);
|
||||
assertThat(value, is(equalTo("test")));
|
||||
assertThat(cacheLoader.wasCalled(), is(true));
|
||||
assertThat(value).isEqualTo("test");
|
||||
assertThat(cacheLoader.wasCalled()).isTrue();
|
||||
}
|
||||
|
||||
public void thread2() {
|
||||
@@ -219,41 +221,39 @@ public class GemfireCacheTest extends AbstractNativeCacheTest<Region<Object, Obj
|
||||
|
||||
Thread.currentThread().setName("Cache Reader Thread");
|
||||
|
||||
TestCacheLoader<String> illegalCacheLoader = new TestCacheLoader<String>("illegal");
|
||||
TestValueLoader<String> illegalCacheLoader = new TestValueLoader<String>("illegal");
|
||||
|
||||
String value = cache.get("key", illegalCacheLoader);
|
||||
|
||||
assertTick(2);
|
||||
assertThat(value, is(equalTo("test")));
|
||||
assertThat(illegalCacheLoader.wasCalled(), is(false));
|
||||
assertThat(value).isEqualTo("test");
|
||||
assertThat(illegalCacheLoader.wasCalled()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class TestCacheLoader<T> implements Callable<T> {
|
||||
protected static class TestValueLoader<T> implements Callable<T> {
|
||||
|
||||
protected static final TestCacheLoader<Object> NULL_VALUE = new TestCacheLoader<Object>();
|
||||
protected static final TestValueLoader<Object> NULL_VALUE = new TestValueLoader<Object>();
|
||||
|
||||
private volatile boolean called;
|
||||
private AtomicBoolean called = new AtomicBoolean(false);
|
||||
|
||||
private final T value;
|
||||
|
||||
public TestCacheLoader() {
|
||||
public TestValueLoader() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public TestCacheLoader(T value) {
|
||||
public TestValueLoader(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
protected boolean wasCalled() {
|
||||
boolean called = this.called;
|
||||
this.called = false;
|
||||
return called;
|
||||
return called.compareAndSet(true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T call() throws Exception {
|
||||
called = true;
|
||||
called.set(true);
|
||||
|
||||
if (value instanceof Exception) {
|
||||
throw (Exception) value;
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright 2012 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 static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
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.when;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.gemstone.gemfire.cache.GemFireCache;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.cache.Cache;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GemfireCacheManager}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GemfireCacheManagerUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private GemFireCache mockGemFireCache;
|
||||
|
||||
private GemfireCacheManager cacheManager;
|
||||
|
||||
@Mock
|
||||
private Region mockRegion;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
cacheManager = new GemfireCacheManager();
|
||||
}
|
||||
|
||||
protected <T> Set<T> asSet(T... elements) {
|
||||
Set<T> set = new HashSet<T>(elements.length);
|
||||
Collections.addAll(set, elements);
|
||||
return set;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Region<?, ?> mockRegion(String name) {
|
||||
Region<?, ?> mockRegion = mock(Region.class, name);
|
||||
when(mockRegion.getName()).thenReturn(name);
|
||||
return mockRegion;
|
||||
}
|
||||
|
||||
protected Region<?, ?> regionFor(Iterable<Region<?, ?>> regions, String name) {
|
||||
for (Region<?, ?> region : regions) {
|
||||
if (region.getName().equals(name)) {
|
||||
return region;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertGemFireCacheAvailableWithAvailableGemFireCacheIsSuccessful() {
|
||||
when(mockGemFireCache.isClosed()).thenReturn(false);
|
||||
assertThat(cacheManager.assertGemFireCacheAvailable(mockGemFireCache)).isSameAs(mockGemFireCache);
|
||||
verify(mockGemFireCache, times(1)).isClosed();
|
||||
verify(mockGemFireCache, times(1)).getName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertGemFireCacheAvailableWithNullThrowsIllegalStateException() {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("A GemFire cache instance is required")));
|
||||
|
||||
cacheManager.assertGemFireCacheAvailable(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertGemFireCacheAvailableWithNamedClosedGemFireCacheThrowsIllegalStateException() {
|
||||
when(mockGemFireCache.isClosed()).thenReturn(true);
|
||||
when(mockGemFireCache.getName()).thenReturn("Example");
|
||||
|
||||
try {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("GemFire cache [Example] has been closed")));
|
||||
|
||||
cacheManager.assertGemFireCacheAvailable(mockGemFireCache);
|
||||
}
|
||||
finally {
|
||||
verify(mockGemFireCache,times(1)).isClosed();
|
||||
verify(mockGemFireCache, times(1)).getName();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertGemFireRegionAvailableWithAvailableGemFireRegionIsSuccessful() {
|
||||
when(mockRegion.isDestroyed()).thenReturn(false);
|
||||
assertThat(cacheManager.assertGemFireRegionAvailable(mockRegion, "Example")).isSameAs(mockRegion);
|
||||
verify(mockRegion, times(1)).isDestroyed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertGemFireRegionAvailableWithNullThrowIllegalStateException() {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("No Region for cache name [Example] was found")));
|
||||
|
||||
cacheManager.assertGemFireRegionAvailable(null, "Example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertGemFireRegionAvailableWithDestroyedGemFireRegionThrowIllegalStateException() {
|
||||
when(mockRegion.isDestroyed()).thenReturn(true);
|
||||
|
||||
try {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("Region [Example] has been destroyed")));
|
||||
|
||||
cacheManager.assertGemFireRegionAvailable(mockRegion, "Example");
|
||||
}
|
||||
finally {
|
||||
verify(mockRegion, times(1)).isDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadCachesIsSuccessful() {
|
||||
Set<Region<?, ?>> regions = asSet(mockRegion("one"), mockRegion("two"), mockRegion("three"));
|
||||
|
||||
cacheManager.setRegions(regions);
|
||||
|
||||
Collection<Cache> loadedCaches = cacheManager.loadCaches();
|
||||
|
||||
assertThat(loadedCaches).isNotNull();
|
||||
assertThat(loadedCaches.size()).isEqualTo(3);
|
||||
|
||||
for (Cache cache : loadedCaches) {
|
||||
assertThat(cache).isInstanceOf(GemfireCache.class);
|
||||
assertThat(regionFor(regions, cache.getName())).isSameAs(cache.getNativeCache());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveRegionsReturnsGivenRegions() {
|
||||
Set<Region<?, ?>> regions = asSet(mockRegion("one"), mockRegion("two"));
|
||||
|
||||
assertThat(cacheManager.resolveRegions(mockGemFireCache, regions, asSet("three", "four"))).isSameAs(regions);
|
||||
assertThat(cacheManager.isDynamic()).isFalse();
|
||||
|
||||
verify(mockGemFireCache, never()).getRegion(anyString());
|
||||
verify(mockGemFireCache, never()).rootRegions();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void resolveRegionsReturnsRegionsForCacheNamesOnly() {
|
||||
Region mockRegionOne = mockRegion("one");
|
||||
Region mockRegionTwo = mockRegion("two");
|
||||
Region mockRegionThree = mockRegion("three");
|
||||
|
||||
when(mockGemFireCache.getRegion(eq("one"))).thenReturn(mockRegionOne);
|
||||
when(mockGemFireCache.getRegion(eq("two"))).thenReturn(mockRegionTwo);
|
||||
when(mockGemFireCache.getRegion(eq("three"))).thenReturn(mockRegionThree);
|
||||
|
||||
Set<Region<?, ?>> regions = cacheManager.resolveRegions(mockGemFireCache, null, asSet("one", "two"));
|
||||
|
||||
assertThat(regions).isNotNull();
|
||||
assertThat(regions.size()).isEqualTo(2);
|
||||
assertThat(regions).containsAll(this.<Region<?, ?>>asSet(mockRegionOne, mockRegionTwo));
|
||||
assertThat(cacheManager.isDynamic()).isFalse();
|
||||
|
||||
verify(mockGemFireCache, times(1)).getRegion(eq("one"));
|
||||
verify(mockGemFireCache, times(1)).getRegion(eq("two"));
|
||||
verify(mockGemFireCache, never()).getRegion(eq("three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveRegionsReturnsGemFireCacheRootRegions() {
|
||||
Set<Region<?, ?>> rootRegions = asSet(mockRegion("one"), mockRegion("two"));
|
||||
|
||||
when(mockGemFireCache.rootRegions()).thenReturn(rootRegions);
|
||||
|
||||
assertThat(cacheManager.resolveRegions(mockGemFireCache, null, null)).isSameAs(rootRegions);
|
||||
assertThat(cacheManager.isDynamic()).isTrue();
|
||||
|
||||
verify(mockGemFireCache, times(1)).rootRegions();
|
||||
verify(mockGemFireCache, never()).getRegion(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSetForNonNullNonEmptyIterableIsTrue() {
|
||||
assertThat(cacheManager.isSet(Collections.singleton(1))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSetForNullIterableIsFalse() {
|
||||
assertThat(cacheManager.isSet(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSetForEmptyIterableIsFalse() {
|
||||
assertThat(cacheManager.isSet(Collections.emptyList())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void regionForCacheNameReturnsRegion() {
|
||||
when(mockGemFireCache.isClosed()).thenReturn(false);
|
||||
when(mockGemFireCache.getName()).thenReturn("regionForCacheNameReturnsRegion");
|
||||
when(mockGemFireCache.getRegion(eq("Example"))).thenReturn(mockRegion);
|
||||
when(mockRegion.isDestroyed()).thenReturn(false);
|
||||
|
||||
assertThat(cacheManager.regionFor(mockGemFireCache, "Example")).isSameAs(mockRegion);
|
||||
|
||||
verify(mockGemFireCache, times(1)).isClosed();
|
||||
verify(mockGemFireCache, times(1)).getName();
|
||||
verify(mockGemFireCache, times(1)).getRegion(eq("Example"));
|
||||
verify(mockRegion, times(1)).isDestroyed();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getMissingCacheReturnsMissingCache() {
|
||||
Region mockRegion = mockRegion("missing");
|
||||
|
||||
when(mockGemFireCache.getRegion(eq("missing"))).thenReturn(mockRegion);
|
||||
|
||||
cacheManager.setCache(mockGemFireCache);
|
||||
|
||||
Cache cache = cacheManager.getMissingCache("missing");
|
||||
|
||||
assertThat(cache).isNotNull();
|
||||
assertThat(cache.getNativeCache()).isEqualTo(mockRegion);
|
||||
|
||||
verify(mockGemFireCache, times(1)).getRegion(eq("missing"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMissingCacheReturnsNull() {
|
||||
cacheManager.setRegions(Collections.<Region<?, ?>>singleton(mockRegion("one")));
|
||||
cacheManager.afterPropertiesSet();
|
||||
|
||||
assertThat(cacheManager.isDynamic()).isFalse();
|
||||
assertThat(cacheManager.getMissingCache("missing")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetCache() {
|
||||
assertThat(cacheManager.getCache()).isNull();
|
||||
|
||||
cacheManager.setCache(mockGemFireCache);
|
||||
|
||||
assertThat(cacheManager.getCache()).isSameAs(mockGemFireCache);
|
||||
|
||||
cacheManager.setCache(null);
|
||||
|
||||
assertThat(cacheManager.getCache()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetCacheNames() {
|
||||
Set<Region<?, ?>> regions = asSet(mockRegion("one"), mockRegion("two"));
|
||||
|
||||
cacheManager.setRegions(regions);
|
||||
cacheManager.afterPropertiesSet();
|
||||
|
||||
assertThat(cacheManager.getCacheNames()).containsAll(asSet("one", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetRegions() {
|
||||
Set<Region<?, ?>> regions = asSet(mockRegion("one"), mockRegion("two"));
|
||||
|
||||
assertThat(cacheManager.getRegions()).isNull();
|
||||
|
||||
cacheManager.setRegions(regions);
|
||||
|
||||
assertThat(cacheManager.getRegions()).isSameAs(regions);
|
||||
|
||||
cacheManager.setRegions(null);
|
||||
|
||||
assertThat(cacheManager.getRegions()).isNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 2012 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 static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isA;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.cache.Cache;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GemfireCache}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.support.GemfireCache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GemfireCacheUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private Callable mockCallable;
|
||||
|
||||
@Mock
|
||||
private Region mockRegion;
|
||||
|
||||
@Test
|
||||
public void wrapIsSuccessful() {
|
||||
GemfireCache gemfireCache = GemfireCache.wrap(mockRegion);
|
||||
|
||||
assertThat(gemfireCache).isNotNull();
|
||||
assertThat(gemfireCache.getNativeCache()).isEqualTo(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructGemfireCacheWithNullRegion() {
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("GemFire Region must not be null")));
|
||||
|
||||
new GemfireCache(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNameReturnsRegionName() {
|
||||
when(mockRegion.getName()).thenReturn("Example");
|
||||
assertThat(GemfireCache.wrap(mockRegion).getName()).isEqualTo("Example");
|
||||
verify(mockRegion, times(1)).getName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearCallsRegionClear() {
|
||||
GemfireCache.wrap(mockRegion).clear();
|
||||
verify(mockRegion, times(1)).clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evictCallsRegionDestoryWithKey() {
|
||||
GemfireCache.wrap(mockRegion).evict("key");
|
||||
verify(mockRegion, times(1)).destroy(eq("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsValueWrapperForKey() {
|
||||
when(mockRegion.get(eq("key"))).thenReturn("test");
|
||||
|
||||
Cache.ValueWrapper value = GemfireCache.wrap(mockRegion).get("key");
|
||||
|
||||
assertThat(value).isNotNull();
|
||||
assertThat(value.get()).isEqualTo("test");
|
||||
|
||||
verify(mockRegion, times(1)).get(eq("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsNullForKey() {
|
||||
when(mockRegion.get(anyString())).thenReturn(null);
|
||||
assertThat(GemfireCache.wrap(mockRegion).get("key")).isNull();
|
||||
verify(mockRegion, times(1)).get(eq("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsValueForKeyAsDesiredType() {
|
||||
when(mockRegion.get(eq("key"))).thenReturn(1);
|
||||
|
||||
Object value = GemfireCache.wrap(mockRegion).get("key", Integer.class);
|
||||
|
||||
assertThat(value).isNotNull();
|
||||
assertThat(value).isInstanceOf(Integer.class);
|
||||
assertThat(value).isEqualTo(1);
|
||||
|
||||
verify(mockRegion, times(1)).get(eq("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsNullForKeyAsDesiredType() {
|
||||
when(mockRegion.get(eq("key"))).thenReturn(null);
|
||||
assertThat(GemfireCache.wrap(mockRegion).get("key", Double.class)).isNull();
|
||||
verify(mockRegion, times(1)).get(eq("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsValueForKeyWithNullDesiredType() {
|
||||
when(mockRegion.get(eq("key"))).thenReturn(true);
|
||||
assertThat(GemfireCache.wrap(mockRegion).get("key", (Class<Boolean>) null)).isTrue();
|
||||
verify(mockRegion, times(1)).get(eq("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getThrowsIllegalStateExceptionForKeyWhenValueIsNotAnInstanceOfDesiredType() {
|
||||
when(mockRegion.get(eq("key"))).thenReturn(1);
|
||||
|
||||
try {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(String.format("Cached value [1] is not an instance of type [%s]",
|
||||
Boolean.class.getName()));
|
||||
|
||||
GemfireCache.wrap(mockRegion).get("key", Boolean.class);
|
||||
}
|
||||
finally {
|
||||
verify(mockRegion, times(1)).get(eq("key"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsValueFromCacheForKeyWithValueLoader() {
|
||||
when(mockRegion.get(eq("key"))).thenReturn("test");
|
||||
assertThat(GemfireCache.wrap(mockRegion).get("key", mockCallable)).isEqualTo("test");
|
||||
verify(mockRegion, times(1)).get(eq("key"));
|
||||
verifyZeroInteractions(mockCallable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsValueFromCacheForKeyAfterSynchronizationWithValueLoader() {
|
||||
when(mockRegion.get(eq("key"))).thenReturn(null).thenReturn("test");
|
||||
assertThat(GemfireCache.wrap(mockRegion).get("key", mockCallable)).isEqualTo("test");
|
||||
verify(mockRegion, times(2)).get(eq("key"));
|
||||
verifyZeroInteractions(mockCallable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReturnsValueFromValueLoaderForKeyWithValueLoader() throws Exception {
|
||||
when(mockRegion.get(anyString())).thenReturn(null);
|
||||
when(mockCallable.call()).thenReturn("mockValue");
|
||||
assertThat(GemfireCache.wrap(mockRegion).get("key", mockCallable)).isEqualTo("mockValue");
|
||||
verify(mockRegion, times(2)).get(eq("key"));
|
||||
verify(mockCallable, times(1)).call();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getThrowsValueRetrievalExceptionForKeyWithValueLoader() throws Exception {
|
||||
when(mockRegion.get(anyString())).thenReturn(null);
|
||||
when(mockCallable.call()).thenThrow(new IllegalStateException("test"));
|
||||
|
||||
try {
|
||||
exception.expect(Cache.ValueRetrievalException.class);
|
||||
exception.expectCause(isA(IllegalStateException.class));
|
||||
|
||||
GemfireCache.wrap(mockRegion).get("key", mockCallable);
|
||||
}
|
||||
finally {
|
||||
verify(mockRegion, times(2)).get(eq("key"));
|
||||
verify(mockCallable, times(1)).call();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putCachesValue() {
|
||||
GemfireCache.wrap(mockRegion).put("key", "test");
|
||||
verify(mockRegion, times(1)).put(eq("key"), eq("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putDoesNotCacheNull() {
|
||||
GemfireCache.wrap(mockRegion).put("key", null);
|
||||
verify(mockRegion, never()).put(anyString(), anyObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putIfAbsentReturnsExistingValue() {
|
||||
when(mockRegion.putIfAbsent(eq("key"), anyObject())).thenReturn("test");
|
||||
|
||||
Cache.ValueWrapper value = GemfireCache.wrap(mockRegion).putIfAbsent("key", "mockValue");
|
||||
|
||||
assertThat(value).isNotNull();
|
||||
assertThat(value.get()).isEqualTo("test");
|
||||
|
||||
verify(mockRegion, times(1)).putIfAbsent(eq("key"), eq("mockValue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putIfAbsentReturnsNull() {
|
||||
when(mockRegion.putIfAbsent(eq("key"), anyObject())).thenReturn(null);
|
||||
|
||||
Cache.ValueWrapper value = GemfireCache.wrap(mockRegion).putIfAbsent("key", "mockValue");
|
||||
|
||||
assertThat(value).isNull();
|
||||
|
||||
verify(mockRegion, times(1)).putIfAbsent(eq("key"), eq("mockValue"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user