From 56c25da97cef237ce05f96e24d6817fc37fb983e Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Tue, 29 Mar 2011 20:20:47 +0300 Subject: [PATCH 1/5] SGF-35 draft for client cache support --- .../data/gemfire/CacheFactoryBean.java | 34 ++++++-- .../client/ClientCacheFactoryBean.java | 87 +++++++++++++++++++ 2 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java index c1ec3ac3..cb979466 100644 --- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java @@ -55,7 +55,7 @@ import com.gemstone.gemfire.distributed.DistributedSystem; public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean, InitializingBean, FactoryBean, PersistenceExceptionTranslator { - private static final Log log = LogFactory.getLog(CacheFactoryBean.class); + protected final Log log = LogFactory.getLog(getClass()); private Cache cache; private Resource cacheXml; @@ -88,14 +88,14 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl th.setContextClassLoader(beanClassLoader); // first look for open caches String msg = null; - try { - cache = CacheFactory.getInstance(system); - msg = "Retrieved existing"; - } catch (CacheClosedException ex) { - // fall back to cache creation - cache = CacheFactory.create(system); + cache = fetchExistingCache(system); + if (cache == null) { + cache = createCache(system); msg = "Created"; } + else { + msg = "Retrieved existing"; + } log.info(msg + " GemFire v." + CacheFactory.getVersion() + " Cache [" + cache.getName() + "]"); @@ -111,6 +111,18 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl } } + protected Cache fetchExistingCache(DistributedSystem system) { + try { + return CacheFactory.getInstance(system); + } catch (CacheClosedException ex) { + return null; + } + } + + protected Cache createCache(DistributedSystem system) throws Exception { + return CacheFactory.create(system); + } + private Properties mergeProperties() { Properties cfgProps = (properties != null ? (Properties) properties.clone() : new Properties()); return cfgProps; @@ -158,10 +170,18 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl return true; } + protected ClassLoader getBeanClassLoader() { + return beanClassLoader; + } + public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } + protected BeanFactory getBeanFactory() { + return beanFactory; + } + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } diff --git a/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java new file mode 100644 index 00000000..f885290e --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java @@ -0,0 +1,87 @@ +/* + * Copyright 2011 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 java.util.concurrent.Callable; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.data.gemfire.CacheFactoryBean; +import org.springframework.util.Assert; + +import com.gemstone.gemfire.cache.Cache; +import com.gemstone.gemfire.cache.client.ClientCacheFactory; +import com.gemstone.gemfire.cache.client.Pool; +import com.gemstone.gemfire.distributed.DistributedSystem; + +/** + * FactoryBean dedicated to creating client caches (caches for client JVMs). + * Intended mainly for usage with GemFire 6.5 (while preserving 6.0 compatibility). + * + * @author Costin Leau + */ +public class ClientCacheFactoryBean extends CacheFactoryBean { + + private String poolName; + private boolean GEMFIRE65 = false; + + @Override + protected Cache createCache(final DistributedSystem system) throws Exception { + initPool(); + + if (GEMFIRE65) { + Callable call = new Callable() { + public Cache call() throws Exception { + return (Cache) new ClientCacheFactory(system.getProperties()).create(); + } + }; + return call.call(); + } + return super.createCache(system); + } + + private void initPool() { + BeanFactory beanFactory = getBeanFactory(); + + // try to eagerly initialize the pool name, if defined as a bean + if (beanFactory.isTypeMatch(poolName, Pool.class)) { + if (log.isDebugEnabled()) { + log.debug("Found bean definition for pool '" + poolName + "'. Eagerly initializing it..."); + } + beanFactory.getBean(poolName, Pool.class); + } + } + + /** + * Sets the pool name used by this client. + * + * @param poolName + */ + public void setPoolName(String poolName) { + Assert.hasText(poolName, "pool name is required"); + this.poolName = poolName; + } + + /** + * Sets the pool used by this client. + * + * @param pool + */ + public void setPool(Pool pool) { + Assert.notNull(pool, "pool cannot be null"); + setPoolName(pool.getName()); + } +} From 3d5f14cc3b467cc42500effae6bd5811a4f6465a Mon Sep 17 00:00:00 2001 From: David Turanski Date: Thu, 7 Jul 2011 09:53:15 -0400 Subject: [PATCH 2/5] added failing ClientCacheTest --- .../data/gemfire/client/ClientCacheTest.java | 15 +++++++++++++++ .../data/gemfire/client/client-cache.xml | 15 +++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java create mode 100644 src/test/resources/org/springframework/data/gemfire/client/client-cache.xml diff --git a/src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java b/src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java new file mode 100644 index 00000000..42270477 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/client/ClientCacheTest.java @@ -0,0 +1,15 @@ +package org.springframework.data.gemfire.client; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("client-cache.xml") +public class ClientCacheTest { + @Test + public void test() { + + } +} diff --git a/src/test/resources/org/springframework/data/gemfire/client/client-cache.xml b/src/test/resources/org/springframework/data/gemfire/client/client-cache.xml new file mode 100644 index 00000000..e4120de8 --- /dev/null +++ b/src/test/resources/org/springframework/data/gemfire/client/client-cache.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + From 3205db109f914dde844573352f30a8ef4a08c066 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Fri, 8 Jul 2011 17:53:15 +0300 Subject: [PATCH 3/5] + retrofitted client cache onto the master + the pool/client cache loop still exists --- .../data/gemfire/CacheFactoryBean.java | 48 +++++++++++++---- .../client/ClientCacheFactoryBean.java | 53 +++++++++---------- .../data/gemfire/client/PoolFactoryBean.java | 2 +- .../data/gemfire/client/client-cache.xml | 2 +- 4 files changed, 65 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java index ee0751cd..c6f5f4e9 100644 --- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java @@ -38,6 +38,7 @@ import com.gemstone.gemfire.GemFireException; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheFactory; +import com.gemstone.gemfire.cache.client.ClientCacheFactory; import com.gemstone.gemfire.distributed.DistributedMember; import com.gemstone.gemfire.distributed.DistributedSystem; import com.gemstone.gemfire.pdx.PdxSerializable; @@ -61,19 +62,33 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl private class PdxOptions implements Runnable { - private CacheFactory factory; + private Object factory; - PdxOptions(CacheFactory factory) { + PdxOptions(Object factory) { this.factory = factory; } public void run() { Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used"); - factory.setPdxSerializer((PdxSerializer) pdxSerializer); - factory.setPdxDiskStore(pdxDiskStoreName); - factory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields); - factory.setPdxPersistent(pdxPersistent); - factory.setPdxReadSerialized(pdxReadSerialized); + + // ugly duplication to go around the different factory hierarchy + if (factory instanceof CacheFactory) { + CacheFactory cf = (CacheFactory) factory; + + cf.setPdxSerializer((PdxSerializer) pdxSerializer); + cf.setPdxDiskStore(pdxDiskStoreName); + cf.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields); + cf.setPdxPersistent(pdxPersistent); + cf.setPdxReadSerialized(pdxReadSerialized); + } + if (factory instanceof ClientCacheFactory) { + ClientCacheFactory cf = (ClientCacheFactory) factory; + cf.setPdxSerializer((PdxSerializer) pdxSerializer); + cf.setPdxDiskStore(pdxDiskStoreName); + cf.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields); + cf.setPdxPersistent(pdxPersistent); + cf.setPdxReadSerialized(pdxReadSerialized); + } } } @@ -104,7 +119,6 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl factoryLocator.afterPropertiesSet(); } Properties cfgProps = mergeProperties(); - CacheFactory factory = new CacheFactory(cfgProps); // use the bean class loader to load Declarable classes Thread th = Thread.currentThread(); @@ -115,9 +129,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl // first look for open caches String msg = null; try { - cache = CacheFactory.getAnyInstance(); + cache = fetchCache(); msg = "Retrieved existing"; } catch (CacheClosedException ex) { + Object factory = createFactory(cfgProps); + // GemFire 6.6 specific options if (pdxSerializer != null || pdxPersistent != null || pdxReadSerialized != null || pdxIgnoreUnreadFields != null || pdxDiskStoreName != null) { @@ -127,7 +143,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl } // fall back to cache creation - cache = factory.create(); + cache = createCache(factory); msg = "Created"; } @@ -151,6 +167,18 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl } } + protected Object createFactory(Properties props) { + return new CacheFactory(props); + } + + protected Cache fetchCache() { + return CacheFactory.getAnyInstance(); + } + + protected Cache createCache(Object factory) { + return ((CacheFactory) factory).create(); + } + private Properties mergeProperties() { Properties cfgProps = (properties != null ? (Properties) properties.clone() : new Properties()); return cfgProps; diff --git a/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java index f885290e..37a6f991 100644 --- a/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java @@ -16,55 +16,52 @@ package org.springframework.data.gemfire.client; -import java.util.concurrent.Callable; +import java.util.Properties; -import org.springframework.beans.factory.BeanFactory; import org.springframework.data.gemfire.CacheFactoryBean; import org.springframework.util.Assert; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.client.ClientCacheFactory; import com.gemstone.gemfire.cache.client.Pool; -import com.gemstone.gemfire.distributed.DistributedSystem; /** * FactoryBean dedicated to creating client caches (caches for client JVMs). - * Intended mainly for usage with GemFire 6.5 (while preserving 6.0 compatibility). + * Acts an utility class (as client caches are a subset with a particular configuration of the generic cache). * * @author Costin Leau */ public class ClientCacheFactoryBean extends CacheFactoryBean { private String poolName; - private boolean GEMFIRE65 = false; @Override - protected Cache createCache(final DistributedSystem system) throws Exception { - initPool(); - - if (GEMFIRE65) { - Callable call = new Callable() { - public Cache call() throws Exception { - return (Cache) new ClientCacheFactory(system.getProperties()).create(); - } - }; - return call.call(); - } - return super.createCache(system); + protected Cache createCache(Object factory) { + return (Cache) ((ClientCacheFactory) factory).create(); } - private void initPool() { - BeanFactory beanFactory = getBeanFactory(); - - // try to eagerly initialize the pool name, if defined as a bean - if (beanFactory.isTypeMatch(poolName, Pool.class)) { - if (log.isDebugEnabled()) { - log.debug("Found bean definition for pool '" + poolName + "'. Eagerly initializing it..."); - } - beanFactory.getBean(poolName, Pool.class); - } + @Override + protected Object createFactory(Properties props) { + return new ClientCacheFactory(props); } + @Override + protected Cache fetchCache() { + return (Cache) ClientCacheFactory.getAnyInstance(); + } + + // private void initPool() { + // BeanFactory beanFactory = getBeanFactory(); + // + // // try to eagerly initialize the pool name, if defined as a bean + // if (beanFactory.isTypeMatch(poolName, Pool.class)) { + // if (log.isDebugEnabled()) { + // log.debug("Found bean definition for pool '" + poolName + "'. Eagerly initializing it..."); + // } + // beanFactory.getBean(poolName, Pool.class); + // } + // } + /** * Sets the pool name used by this client. * @@ -84,4 +81,4 @@ public class ClientCacheFactoryBean extends CacheFactoryBean { Assert.notNull(pool, "pool cannot be null"); setPoolName(pool.getName()); } -} +} \ No newline at end of file diff --git a/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java index 9bab6b96..fcbdfc94 100644 --- a/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/client/PoolFactoryBean.java @@ -55,7 +55,7 @@ public class PoolFactoryBean implements FactoryBean, InitializingBean, Dis private static final Log log = LogFactory.getLog(PoolFactoryBean.class); - // whether the pool has been created internaly or not + // whether the pool has been created internally or not private boolean internalPool = true; private Pool pool; diff --git a/src/test/resources/org/springframework/data/gemfire/client/client-cache.xml b/src/test/resources/org/springframework/data/gemfire/client/client-cache.xml index e4120de8..748ce520 100644 --- a/src/test/resources/org/springframework/data/gemfire/client/client-cache.xml +++ b/src/test/resources/org/springframework/data/gemfire/client/client-cache.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + From 69440922555a8b2bd88ff4f279e59fa6947c24d6 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Wed, 24 Aug 2011 21:07:09 +0300 Subject: [PATCH 4/5] SGF-35 + add more meat to the client-cache server + add a dedicated FactoryBean plus namespace --- .../data/gemfire/CacheFactoryBean.java | 80 ++++++------ .../client/ClientCacheFactoryBean.java | 114 +++++++++++++++--- .../gemfire/config/ClientCacheParser.java | 41 +++++++ .../config/GemfireNamespaceHandler.java | 2 + .../gemfire/config/spring-gemfire-1.1.xsd | 94 ++++++++++----- 5 files changed, 246 insertions(+), 85 deletions(-) create mode 100644 src/main/java/org/springframework/data/gemfire/config/ClientCacheParser.java diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java index c6f5f4e9..81bd13e0 100644 --- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java @@ -38,7 +38,7 @@ import com.gemstone.gemfire.GemFireException; import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheFactory; -import com.gemstone.gemfire.cache.client.ClientCacheFactory; +import com.gemstone.gemfire.cache.GemFireCache; import com.gemstone.gemfire.distributed.DistributedMember; import com.gemstone.gemfire.distributed.DistributedSystem; import com.gemstone.gemfire.pdx.PdxSerializable; @@ -58,43 +58,35 @@ import com.gemstone.gemfire.pdx.PdxSerializer; * @author Costin Leau */ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean, - InitializingBean, FactoryBean, PersistenceExceptionTranslator { + InitializingBean, FactoryBean, PersistenceExceptionTranslator { + /** + * Inner class to avoid a hard dependency on the GemFire 6.6 API. + * + * @author Costin Leau + */ private class PdxOptions implements Runnable { - private Object factory; + private CacheFactory factory; - PdxOptions(Object factory) { + PdxOptions(CacheFactory factory) { this.factory = factory; } public void run() { Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used"); - // ugly duplication to go around the different factory hierarchy - if (factory instanceof CacheFactory) { - CacheFactory cf = (CacheFactory) factory; - - cf.setPdxSerializer((PdxSerializer) pdxSerializer); - cf.setPdxDiskStore(pdxDiskStoreName); - cf.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields); - cf.setPdxPersistent(pdxPersistent); - cf.setPdxReadSerialized(pdxReadSerialized); - } - if (factory instanceof ClientCacheFactory) { - ClientCacheFactory cf = (ClientCacheFactory) factory; - cf.setPdxSerializer((PdxSerializer) pdxSerializer); - cf.setPdxDiskStore(pdxDiskStoreName); - cf.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields); - cf.setPdxPersistent(pdxPersistent); - cf.setPdxReadSerialized(pdxReadSerialized); - } + factory.setPdxSerializer((PdxSerializer) pdxSerializer); + factory.setPdxDiskStore(pdxDiskStoreName); + factory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields); + factory.setPdxPersistent(pdxPersistent); + factory.setPdxReadSerialized(pdxReadSerialized); } } - private static final Log log = LogFactory.getLog(CacheFactoryBean.class); + protected final Log log = LogFactory.getLog(getClass()); - private Cache cache; + private GemFireCache cache; private Resource cacheXml; private Properties properties; private ClassLoader beanClassLoader; @@ -104,11 +96,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl private String beanName; private boolean useBeanFactoryLocator = true; // PDX options - private Object pdxSerializer; - private Boolean pdxPersistent; - private Boolean pdxReadSerialized; - private Boolean pdxIgnoreUnreadFields; - private String pdxDiskStoreName; + protected Object pdxSerializer; + protected Boolean pdxPersistent; + protected Boolean pdxReadSerialized; + protected Boolean pdxIgnoreUnreadFields; + protected String pdxDiskStoreName; public void afterPropertiesSet() throws Exception { // initialize locator @@ -139,7 +131,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl || pdxIgnoreUnreadFields != null || pdxDiskStoreName != null) { Assert.isTrue(ClassUtils.isPresent("com.gemstone.gemfire.pdx.PdxSerializer", beanClassLoader), "Cannot set PDX options since GemFire 6.6 not detected"); - new PdxOptions(factory).run(); + applyPdxOptions(factory); } // fall back to cache creation @@ -152,7 +144,6 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl log.info("Connected to Distributed System [" + system.getName() + "=" + member.getId() + "@" + member.getHost() + "]"); - log.info(msg + " GemFire v." + CacheFactory.getVersion() + " Cache [" + cache.getName() + "]"); // load/init cache.xml @@ -162,20 +153,32 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl if (log.isDebugEnabled()) log.debug("Initialized cache from " + cacheXml); + } finally { th.setContextClassLoader(oldTCCL); } } + /** + * Sets the PDX properties for the given object. Note this is implementation specific as it depends on the type + * of the factory passed in. + * + * @param factory + */ + protected void applyPdxOptions(Object factory) { + if (factory instanceof CacheFactory) { + new PdxOptions((CacheFactory) factory).run(); + } + } protected Object createFactory(Properties props) { return new CacheFactory(props); } - protected Cache fetchCache() { + protected GemFireCache fetchCache() { return CacheFactory.getAnyInstance(); } - protected Cache createCache(Object factory) { + protected GemFireCache createCache(Object factory) { return ((CacheFactory) factory).create(); } @@ -212,11 +215,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl return null; } - public Cache getObject() throws Exception { + public GemFireCache getObject() throws Exception { return cache; } - public Class getObjectType() { + public Class getObjectType() { return (cache != null ? cache.getClass() : Cache.class); } @@ -310,4 +313,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl public void setPdxDiskStoreName(String pdxDiskStoreName) { this.pdxDiskStoreName = pdxDiskStoreName; } + + /** + * @return the beanFactory + */ + protected BeanFactory getBeanFactory() { + return beanFactory; + } } \ No newline at end of file diff --git a/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java index 37a6f991..2f739c52 100644 --- a/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/client/ClientCacheFactoryBean.java @@ -16,14 +16,19 @@ package org.springframework.data.gemfire.client; +import java.net.InetSocketAddress; +import java.util.List; import java.util.Properties; +import org.springframework.beans.factory.BeanFactory; import org.springframework.data.gemfire.CacheFactoryBean; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; -import com.gemstone.gemfire.cache.Cache; +import com.gemstone.gemfire.cache.GemFireCache; import com.gemstone.gemfire.cache.client.ClientCacheFactory; import com.gemstone.gemfire.cache.client.Pool; +import com.gemstone.gemfire.pdx.PdxSerializer; /** * FactoryBean dedicated to creating client caches (caches for client JVMs). @@ -33,11 +38,38 @@ import com.gemstone.gemfire.cache.client.Pool; */ public class ClientCacheFactoryBean extends CacheFactoryBean { + /** + * Inner class to avoid a hard dependency on the GemFire 6.6 API. + * + * @author Costin Leau + */ + private class PdxOptions implements Runnable { + + private ClientCacheFactory factory; + + PdxOptions(ClientCacheFactory factory) { + this.factory = factory; + } + + public void run() { + Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used"); + + factory.setPdxSerializer((PdxSerializer) pdxSerializer); + factory.setPdxDiskStore(pdxDiskStoreName); + factory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields); + factory.setPdxPersistent(pdxPersistent); + factory.setPdxReadSerialized(pdxReadSerialized); + } + } + private String poolName; + private Pool pool; @Override - protected Cache createCache(Object factory) { - return (Cache) ((ClientCacheFactory) factory).create(); + protected GemFireCache createCache(Object factory) { + ClientCacheFactory ccf = (ClientCacheFactory) factory; + initializePool(ccf); + return ccf.create(); } @Override @@ -46,21 +78,62 @@ public class ClientCacheFactoryBean extends CacheFactoryBean { } @Override - protected Cache fetchCache() { - return (Cache) ClientCacheFactory.getAnyInstance(); + protected GemFireCache fetchCache() { + return ClientCacheFactory.getAnyInstance(); } - // private void initPool() { - // BeanFactory beanFactory = getBeanFactory(); - // - // // try to eagerly initialize the pool name, if defined as a bean - // if (beanFactory.isTypeMatch(poolName, Pool.class)) { - // if (log.isDebugEnabled()) { - // log.debug("Found bean definition for pool '" + poolName + "'. Eagerly initializing it..."); - // } - // beanFactory.getBean(poolName, Pool.class); - // } - // } + private void initializePool(ClientCacheFactory ccf) { + Pool p = pool; + + if (p == null && StringUtils.hasText(poolName)) { + BeanFactory beanFactory = getBeanFactory(); + + // try to eagerly initialize the pool name, if defined as a bean + if (beanFactory.isTypeMatch(poolName, Pool.class)) { + if (log.isDebugEnabled()) { + log.debug("Found bean definition for pool '" + poolName + "'. Eagerly initializing it..."); + } + p = beanFactory.getBean(poolName, Pool.class); + } + } + + if (p != null) { + // copy the pool settings - this way if the pool is not found, at least the cache will have a similar config + ccf.setPoolFreeConnectionTimeout(p.getFreeConnectionTimeout()); + ccf.setPoolIdleTimeout(p.getIdleTimeout()); + ccf.setPoolLoadConditioningInterval(p.getLoadConditioningInterval()); + ccf.setPoolMaxConnections(p.getMaxConnections()); + ccf.setPoolMinConnections(p.getMinConnections()); + ccf.setPoolMultiuserAuthentication(p.getMultiuserAuthentication()); + ccf.setPoolPingInterval(p.getPingInterval()); + ccf.setPoolPRSingleHopEnabled(p.getPRSingleHopEnabled()); + ccf.setPoolReadTimeout(p.getReadTimeout()); + ccf.setPoolRetryAttempts(p.getRetryAttempts()); + ccf.setPoolServerGroup(p.getServerGroup()); + ccf.setPoolSocketBufferSize(p.getSocketBufferSize()); + ccf.setPoolStatisticInterval(p.getStatisticInterval()); + ccf.setPoolSubscriptionAckInterval(p.getSubscriptionAckInterval()); + ccf.setPoolSubscriptionEnabled(p.getSubscriptionEnabled()); + ccf.setPoolSubscriptionMessageTrackingTimeout(p.getSubscriptionMessageTrackingTimeout()); + ccf.setPoolSubscriptionRedundancy(p.getSubscriptionRedundancy()); + ccf.setPoolThreadLocalConnections(p.getThreadLocalConnections()); + + List locators = p.getLocators(); + if (locators != null) { + for (InetSocketAddress inet : locators) { + ccf.addPoolLocator(inet.getHostName(), inet.getPort()); + } + } + + + List servers = p.getServers(); + if (locators != null) { + for (InetSocketAddress inet : servers) { + ccf.addPoolLocator(inet.getHostName(), inet.getPort()); + } + } + } + } /** * Sets the pool name used by this client. @@ -79,6 +152,13 @@ public class ClientCacheFactoryBean extends CacheFactoryBean { */ public void setPool(Pool pool) { Assert.notNull(pool, "pool cannot be null"); - setPoolName(pool.getName()); + this.pool = pool; + } + + @Override + protected void applyPdxOptions(Object factory) { + if (factory instanceof ClientCacheFactory) { + new PdxOptions((ClientCacheFactory) factory).run(); + } } } \ No newline at end of file diff --git a/src/main/java/org/springframework/data/gemfire/config/ClientCacheParser.java b/src/main/java/org/springframework/data/gemfire/config/ClientCacheParser.java new file mode 100644 index 00000000..01683e71 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/ClientCacheParser.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2011 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; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.data.gemfire.client.ClientCacheFactoryBean; +import org.w3c.dom.Element; + +/** + * Parser for <client-cache;gt; definitions. + * + * @author Costin Leau + */ +class ClientCacheParser extends CacheParser { + + @Override + protected Class getBeanClass(Element element) { + return ClientCacheFactoryBean.class; + } + + @Override + protected void doParse(Element element, BeanDefinitionBuilder builder) { + super.doParse(element, builder); + + ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName"); + } +} \ No newline at end of file diff --git a/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java b/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java index 1d4101dd..7882ab01 100644 --- a/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java +++ b/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java @@ -27,6 +27,8 @@ class GemfireNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("cache", new CacheParser()); + registerBeanDefinitionParser("client-cache", new ClientCacheParser()); + registerBeanDefinitionParser("lookup-region", new LookupRegionParser()); registerBeanDefinitionParser("replicated-region", new ReplicatedRegionParser()); registerBeanDefinitionParser("partitioned-region", new PartitionedRegionParser()); diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.1.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.1.xsd index eb43844f..ae6ff94b 100644 --- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.1.xsd +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.1.xsd @@ -17,7 +17,42 @@ ]]> - + + + + + + + + + + + + + + + namespace and its 'properties' element. + ]]> + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + - - - - - namespace and its 'properties' element. - ]]> - - - - - - - + + + + @@ -733,10 +761,10 @@ cache to differ from other caches. - + From a05543b447588caf2486f238b07d6efe0f9c09ab Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Wed, 24 Aug 2011 21:23:04 +0300 Subject: [PATCH 5/5] SGF-35 + more integration tests --- .../gemfire/config/CacheNamespaceTest.java | 18 +++++++++++++++++- .../resources/{cache.xml => gemfire-cache.xml} | 0 src/test/resources/gemfire-client-cache.xml | 11 +++++++++++ .../data/gemfire/config/cache-ns.xml | 6 +++++- 4 files changed, 33 insertions(+), 2 deletions(-) rename src/test/resources/{cache.xml => gemfire-cache.xml} (100%) create mode 100644 src/test/resources/gemfire-client-cache.xml diff --git a/src/test/java/org/springframework/data/gemfire/config/CacheNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/CacheNamespaceTest.java index 16287627..41086663 100644 --- a/src/test/java/org/springframework/data/gemfire/config/CacheNamespaceTest.java +++ b/src/test/java/org/springframework/data/gemfire/config/CacheNamespaceTest.java @@ -27,6 +27,7 @@ import org.springframework.data.gemfire.CacheFactoryBean; import org.springframework.data.gemfire.GemfireBeanFactoryLocator; import org.springframework.data.gemfire.RecreatingContextTest; import org.springframework.data.gemfire.TestUtils; +import org.springframework.data.gemfire.client.ClientCacheFactoryBean; /** * @author Costin Leau @@ -59,7 +60,7 @@ public class CacheNamespaceTest extends RecreatingContextTest { assertTrue(ctx.containsBean("cache-with-xml")); CacheFactoryBean cfb = (CacheFactoryBean) ctx.getBean("&cache-with-xml"); Resource res = TestUtils.readField("cacheXml", cfb); - assertEquals("cache.xml", res.getFilename()); + assertEquals("gemfire-cache.xml", res.getFilename()); assertEquals(ctx.getBean("props"), TestUtils.readField("properties", cfb)); } @@ -76,4 +77,19 @@ public class CacheNamespaceTest extends RecreatingContextTest { } } + @Test + public void testBasicClientCache() throws Exception { + assertTrue(ctx.containsBean("client-cache")); + ClientCacheFactoryBean cfb = (ClientCacheFactoryBean) ctx.getBean("&client-cache"); + assertNull(TestUtils.readField("cacheXml", cfb)); + assertNull(TestUtils.readField("properties", cfb)); + } + + @Test + public void testBasicClientCacheWithXml() throws Exception { + assertTrue(ctx.containsBean("client-cache-with-xml")); + ClientCacheFactoryBean cfb = (ClientCacheFactoryBean) ctx.getBean("&client-cache-with-xml"); + Resource res = TestUtils.readField("cacheXml", cfb); + assertEquals("gemfire-client-cache.xml", res.getFilename()); + } } \ No newline at end of file diff --git a/src/test/resources/cache.xml b/src/test/resources/gemfire-cache.xml similarity index 100% rename from src/test/resources/cache.xml rename to src/test/resources/gemfire-cache.xml diff --git a/src/test/resources/gemfire-client-cache.xml b/src/test/resources/gemfire-client-cache.xml new file mode 100644 index 00000000..11c3a381 --- /dev/null +++ b/src/test/resources/gemfire-client-cache.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/src/test/resources/org/springframework/data/gemfire/config/cache-ns.xml b/src/test/resources/org/springframework/data/gemfire/config/cache-ns.xml index e80adb57..de546d8a 100644 --- a/src/test/resources/org/springframework/data/gemfire/config/cache-ns.xml +++ b/src/test/resources/org/springframework/data/gemfire/config/cache-ns.xml @@ -16,11 +16,15 @@ - + false + + + + \ No newline at end of file