Implemented SGF-206 - CacheLoader and CacheWriter support on client, local Regions in a GemFire ClientCache. Also, performed additional refactoring of related code.

This commit is contained in:
John Blum
2013-10-23 14:23:20 -07:00
parent 8deda7804c
commit 4ed76947d0
11 changed files with 602 additions and 287 deletions

View File

@@ -15,7 +15,10 @@
*/
package org.springframework.data.gemfire.client;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.mockito.Mockito;
@@ -27,14 +30,18 @@ import com.gemstone.gemfire.cache.client.ClientRegionFactory;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.gemstone.gemfire.cache.client.Pool;
/**
* @author David Turanski
* @author John Blum
*/
public class ClientRegionFactoryBeanTest {
@Test
public void testLookupFallbackFailingToUseProvidedShortcut()
throws Exception {
public void testLookupFallbackFailingToUseProvidedShortcut() throws Exception {
ClientRegionFactoryBean<Object, Object> fb = new ClientRegionFactoryBean<Object, Object>();
fb.setShortcut(ClientRegionShortcut.CACHING_PROXY);
Pool pool = Mockito.mock(Pool.class);
BeanFactory beanFactory = Mockito.mock(BeanFactory.class);
@@ -47,11 +54,8 @@ public class ClientRegionFactoryBeanTest {
ClientCache cache = Mockito.mock(ClientCache.class);
@SuppressWarnings("unchecked")
ClientRegionFactory<Object, Object> factory = Mockito
.mock(ClientRegionFactory.class);
Mockito.when(
cache.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY))
.thenReturn(factory);
ClientRegionFactory<Object, Object> factory = Mockito.mock(ClientRegionFactory.class);
Mockito.when(cache.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY)).thenReturn(factory);
@SuppressWarnings("unchecked")
Region<Object, Object> region = Mockito.mock(Region.class);
@@ -61,4 +65,54 @@ public class ClientRegionFactoryBeanTest {
assertSame(region, result);
}
@Test
public void testCloseDestroySettings() {
final ClientRegionFactoryBean<Object, Object> factory = new ClientRegionFactoryBean<Object, Object>();
assertNotNull(factory);
assertFalse(factory.isClose());
assertFalse(factory.isDestroy());
factory.setClose(false);
assertFalse(factory.isClose());
assertFalse(factory.isDestroy()); // when destroy is false it remains false even when setClose(false) is called
factory.setClose(true);
assertTrue(factory.isClose()); // calling setClose(true) should set close to true
assertFalse(factory.isDestroy());
factory.setDestroy(false);
assertTrue(factory.isClose()); // calling setDestroy(false) should have no affect on close
assertFalse(factory.isDestroy());
factory.setDestroy(true);
assertFalse(factory.isClose()); // setting destroy to true should set close to false
assertTrue(factory.isDestroy()); // calling setDestroy(true) should set destroy to true
factory.setClose(false);
assertFalse(factory.isClose());
assertTrue(factory.isDestroy()); // calling setClose(false) should have no affect on destroy
factory.setDestroy(false);
assertFalse(factory.isClose()); // setting destroy back to false should have no affect on close
assertFalse(factory.isDestroy());
factory.setDestroy(true);
assertFalse(factory.isClose());
assertTrue(factory.isDestroy());
factory.setClose(true);
assertTrue(factory.isClose());
assertFalse(factory.isDestroy()); // setting close to true should set destroy to false
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright 2010-2013 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.ForkUtil;
import org.springframework.data.gemfire.fork.SpringCacheServerProcess;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheLoaderException;
import com.gemstone.gemfire.cache.CacheWriterException;
import com.gemstone.gemfire.cache.EntryEvent;
import com.gemstone.gemfire.cache.LoaderHelper;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.util.CacheWriterAdapter;
/**
* The ClientRegionWithCacheLoaderWriterTest class is a test suite of test cases testing the addition of CacheLoaders
* and CacheWriters to a client, local Region inside a GemFire Cache.
* <p/>
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.context.ApplicationContext
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @see com.gemstone.gemfire.cache.CacheLoader
* @see com.gemstone.gemfire.cache.CacheWriter
* @see com.gemstone.gemfire.cache.Region
* @since 1.3.3
*/
@ContextConfiguration(locations = "/org/springframework/data/gemfire/client/clientcache-with-region-using-cache-loader-writer.xml",
initializers = GemfireTestApplicationContextInitializer.class)
@RunWith(SpringJUnit4ClassRunner.class)
@SuppressWarnings("unused")
public class ClientRegionWithCacheLoaderWriterTest {
private static final int REGION_SIZE = 100;
@Autowired
private ApplicationContext context;
@Resource(name = "localAppDataRegion")
private Region<Integer, Integer> localAppData;
@BeforeClass
public static void startCacheServer() throws Exception {
ForkUtil.startCacheServer(SpringCacheServerProcess.class.getName() + " "
+ "/org/springframework/data/gemfire/client/servercache-with-region-for-client.xml");
}
@Test
public void testCacheLoaderWriter() {
assertNotNull(localAppData);
assertEquals(0, localAppData.size());
for (int key = 0; key < REGION_SIZE; key++) {
assertEquals(key + 1, localAppData.get(key).intValue());
}
assertEquals(REGION_SIZE, localAppData.size());
for (int key = 0; key < REGION_SIZE; key++) {
assertEquals(key + 1, localAppData.put(key, REGION_SIZE - key).intValue());
}
LocalAppDataCacheWriter localCacheWriter = context.getBean("localCacheWriter", LocalAppDataCacheWriter.class);
assertNotNull(localCacheWriter);
for (int key = 0; key < REGION_SIZE; key++) {
assertEquals(REGION_SIZE - key, localCacheWriter.get(key).intValue());
}
}
public static class LocalAppDataCacheLoader implements CacheLoader<Integer, Integer> {
private static final AtomicInteger VALUE_GENERATOR = new AtomicInteger(0);
@Override
public Integer load(final LoaderHelper<Integer, Integer> helper) throws CacheLoaderException {
return VALUE_GENERATOR.incrementAndGet();
}
@Override
public void close() {
}
}
public static class LocalAppDataCacheWriter extends CacheWriterAdapter<Integer, Integer> {
private static final Map<Integer, Integer> data = new ConcurrentHashMap<Integer, Integer>(REGION_SIZE);
@Override
public void beforeUpdate(final EntryEvent<Integer, Integer> event) throws CacheWriterException {
data.put(event.getKey(), event.getNewValue());
}
public Integer get(final Integer key) {
return data.get(key);
}
}
}

View File

@@ -12,7 +12,6 @@
*/
package org.springframework.data.gemfire.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
@@ -26,36 +25,41 @@ import org.springframework.data.gemfire.fork.SpringCacheServerProcess;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.Pool;
/**
* @author David Turanski
*
*/
public class MultipleClientCacheTest {
@BeforeClass
public static void startUp() throws Exception {
ForkUtil.startCacheServer(SpringCacheServerProcess.class.getName() + " "
+ "/org/springframework/data/gemfire/client/datasource-server.xml");
+ "/org/springframework/data/gemfire/client/datasource-server.xml");
}
@Test
public void testMultipleCaches() {
String resourcePath = "/org/springframework/data/gemfire/client/client-cache-no-close.xml";
ConfigurableApplicationContext ctx1 = new ClassPathXmlApplicationContext(resourcePath);
ConfigurableApplicationContext ctx2 = new ClassPathXmlApplicationContext(resourcePath);
Region region1 = ctx1.getBean(Region.class);
Cache cache1 = ctx1.getBean(Cache.class);
Pool pool = ctx1.getBean(Pool.class);
Region region2 = ctx2.getBean(Region.class);
Cache cache2 = ctx2.getBean(Cache.class);
assertSame(region1,region2);
assertSame(cache1,cache2);
assertFalse(region1.isDestroyed());
ctx1.close();
ConfigurableApplicationContext context1 = new ClassPathXmlApplicationContext(resourcePath);
ConfigurableApplicationContext context2 = new ClassPathXmlApplicationContext(resourcePath);
Cache cache1 = context1.getBean(Cache.class);
Cache cache2 = context2.getBean(Cache.class);
assertSame(cache1, cache2);
Region region1 = context1.getBean(Region.class);
Region region2 = context2.getBean(Region.class);
assertSame(region1, region2);
assertFalse(cache1.isClosed());
assertFalse("region was destroyed" ,region1.isDestroyed());
assertFalse(region1.isDestroyed());
context1.close();
assertFalse(cache1.isClosed());
assertFalse("region was destroyed", region1.isDestroyed());
}
@AfterClass
@@ -63,4 +67,5 @@ public class MultipleClientCacheTest {
Thread.sleep(3000);
ForkUtil.sendSignal();
}
}

View File

@@ -18,6 +18,7 @@ package org.springframework.data.gemfire.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -38,21 +39,27 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.CacheListener;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheLoaderException;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAlgorithm;
import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.LoaderHelper;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.gemstone.gemfire.cache.util.CacheWriterAdapter;
import com.gemstone.gemfire.cache.util.ObjectSizer;
/**
* @author Costin Leau
* @author David Turanski
* @author John Blum
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="client-ns.xml",
@ContextConfiguration(locations="/org/springframework/data/gemfire/config/client-ns.xml",
initializers=GemfireTestApplicationContextInitializer.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class ClientRegionNamespaceTest {
@Autowired
@@ -60,9 +67,7 @@ public class ClientRegionNamespaceTest {
@AfterClass
public static void tearDown() {
for (String name : new File(".").list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.startsWith("BACKUP");
@@ -94,8 +99,8 @@ public class ClientRegionNamespaceTest {
assertEquals(DataPolicy.EMPTY, TestUtils.readField("dataPolicy", fb));
}
@Test
@SuppressWarnings("rawtypes")
@Test
public void testComplexClient() throws Exception {
assertTrue(context.containsBean("complex"));
ClientRegionFactoryBean fb = context.getBean("&complex", ClientRegionFactoryBean.class);
@@ -135,4 +140,33 @@ public class ClientRegionNamespaceTest {
ObjectSizer sizer = evicAttr.getObjectSizer();
assertEquals(SimpleObjectSizer.class, sizer.getClass());
}
@Test
public void testClientRegionWithCacheLoaderAndCacheWriter() throws Exception {
assertTrue(context.containsBean("loadWithWrite"));
ClientRegionFactoryBean factory = context.getBean("&loadWithWrite", ClientRegionFactoryBean.class);
assertNotNull(factory);
assertEquals(ClientRegionShortcut.LOCAL, TestUtils.readField("shortcut", factory));
assertTrue(TestUtils.readField("cacheLoader", factory) instanceof TestCacheLoader);
assertTrue(TestUtils.readField("cacheWriter", factory) instanceof TestCacheWriter);
}
@SuppressWarnings("unused")
public static final class TestCacheLoader implements CacheLoader<Object, Object> {
@Override
public Object load(final LoaderHelper<Object, Object> helper) throws CacheLoaderException {
throw new UnsupportedOperationException("Not Implemented!");
}
@Override
public void close() {
}
}
public static final class TestCacheWriter extends CacheWriterAdapter<Object, Object> {
}
}