SGF-439 - Add 'durable-client-id' and 'durable-client-timeout' attributes to the <gfe:client-cache> namespace element for convenience.

(cherry picked from commit e74768f006d59210ddd3d4fe5294a60ca505674f)

Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2015-10-15 16:39:12 -07:00
parent 23374a583f
commit 1bb8e7b7a9
14 changed files with 303 additions and 99 deletions

View File

@@ -24,6 +24,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.util.DistributedSystemUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -56,11 +57,13 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
public class ClientCacheFactoryBean extends CacheFactoryBean implements ApplicationListener<ContextRefreshedEvent> {
protected Boolean keepAlive = false;
protected Boolean readyForEvents = false;
protected Integer durableClientTimeout;
private Pool pool;
protected String durableClientId;
protected String poolName;
@Override
@@ -101,6 +104,8 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
gemfireProperties = distributedSystemProperties;
}
DistributedSystemUtils.configureDurableClient(gemfireProperties, durableClientId, durableClientTimeout);
return gemfireProperties;
}
@@ -179,7 +184,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory
*/
private ClientCacheFactory initializePool(ClientCacheFactory clientCacheFactory) {
resolvePool(this.pool);
resolvePool(pool);
return clientCacheFactory;
}
@@ -246,21 +251,62 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
((ClientCache) cache).close(isKeepAlive());
}
@Override
public Class<? extends GemFireCache> getObjectType() {
return (cache != null ? cache.getClass() : ClientCache.class);
}
@Override
public final void setEnableAutoReconnect(final Boolean enableAutoReconnect) {
throw new UnsupportedOperationException("Auto-reconnect is not supported on ClientCache.");
}
/**
* Set the GemFire System property 'durable-client-id' to indicate to the server that this client is durable.
*
* @param durableClientId a String value indicating the durable client id.
*/
public void setDurableClientId(final String durableClientId) {
this.durableClientId = durableClientId;
}
/**
* Gets the value of the GemFire System property 'durable-client-id' indicating to the server whether
* this client is durable.
*
* @return a String value indicating the durable client id.
*/
public String getDurableClientId() {
return durableClientId;
}
/**
* Set the GemFire System property 'durable-client-timeout' indicating to the server how long to track events
* for the durable client when disconnected.
*
* @param durableClientTimeout an Integer value indicating the timeout in seconds for the server to keep
* the durable client's queue around.
*/
public void setDurableClientTimeout(final Integer durableClientTimeout) {
this.durableClientTimeout = durableClientTimeout;
}
/**
* Get the value of the GemFire System property 'durable-client-timeout' indicating to the server how long
* to track events for the durable client when disconnected.
*
* @return an Integer value indicating the timeout in seconds for the server to keep
* the durable client's queue around.
*/
public Integer getDurableClientTimeout() {
return durableClientTimeout;
}
@Override
public final Boolean getEnableAutoReconnect() {
return Boolean.FALSE;
}
@Override
public Class<? extends GemFireCache> getObjectType() {
return (cache != null ? cache.getClass() : ClientCache.class);
}
/**
* Sets whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects.
@@ -271,6 +317,16 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
this.keepAlive = keepAlive;
}
/**
* Gets the user specified value for whether the server(s) should keep the durable client's queue alive
* for the duration of the timeout when the client voluntarily disconnects.
*
* @return a boolean value indicating whether the server should keep the durable client's queues alive.
*/
public Boolean getKeepAlive() {
return keepAlive;
}
/**
* Determines whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects.
@@ -278,7 +334,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
* @return a boolean value indicating whether the server should keep the durable client's queues alive.
*/
public boolean isKeepAlive() {
return Boolean.TRUE.equals(this.keepAlive);
return Boolean.TRUE.equals(getKeepAlive());
}
/**
@@ -311,10 +367,11 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
/**
* Set the readyForEvents flag.
* Sets the readyForEvents property to indicate whether the cache client should notify the server
* that it is ready to receive updates.
*
* @param readyForEvents sets a boolean flag to notify the server that this durable client is ready
* to receive updates.
* @param readyForEvents sets a boolean flag to notify the server that this durable client
* is ready to receive updates.
* @see #getReadyForEvents()
*/
public void setReadyForEvents(Boolean readyForEvents){
@@ -322,7 +379,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean implements Applicat
}
/**
* Gets the value for the readyForEvents property.
* Gets the user-specified value for the readyForEvents property.
*
* @return a boolean value indicating the state of the 'readyForEvents' property.
*/

View File

@@ -108,18 +108,6 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
private String serverGroup = PoolFactory.DEFAULT_SERVER_GROUP;
public Pool getObject() throws Exception {
return pool;
}
public Class<?> getObjectType() {
return (pool != null ? pool.getClass() : Pool.class);
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasText(name)) {
Assert.hasText(beanName, "Pool 'name' is required");
@@ -184,14 +172,20 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
}
}
/* (non-Javadoc) */
/**
* Creates an instance of the GemFire PoolFactory interface to construct, configure and initialize a GemFire Pool.
*
* @return a PoolFactory implementation to create Pool.
* @see com.gemstone.gemfire.cache.client.PoolFactory
* @see com.gemstone.gemfire.cache.client.PoolManager#createFactory()
*/
protected PoolFactory createPoolFactory() {
return PoolManager.createFactory();
}
/* (non-Javadoc) */
void resolveDistributedSystem() {
if (DistributedSystemUtils.getDistributedSystem() == null) {
if (DistributedSystemUtils.isNotConnected(DistributedSystemUtils.getDistributedSystem())) {
doDistributedSystemConnect(resolveGemfireProperties());
}
}
@@ -200,7 +194,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
Properties resolveGemfireProperties() {
try {
ClientCacheFactoryBean clientCacheFactoryBean = beanFactory.getBean(ClientCacheFactoryBean.class);
return clientCacheFactoryBean.getProperties();
return clientCacheFactoryBean.resolveProperties();
}
catch (Exception ignore) {
return null;
@@ -208,8 +202,8 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
}
/**
* A workaround to create a Pool if no ClientCache has been created yet. Initialize a client-like
* Distributed System before initializing the Pool.
* A workaround to create a Pool if no ClientCache has been created yet. Initialize a cache client-like
* DistributedSystem before initializing the Pool.
*
* @param properties GemFire System Properties.
* @see java.util.Properties
@@ -235,6 +229,18 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
}
}
public Pool getObject() throws Exception {
return pool;
}
public Class<?> getObjectType() {
return (pool != null ? pool.getClass() : Pool.class);
}
public boolean isSingleton() {
return true;
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

View File

@@ -38,8 +38,10 @@ class ClientCacheParser extends CacheParser {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
ParsingUtils.setPropertyValue(element, builder, "keep-alive", "keepAlive");
ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName");
ParsingUtils.setPropertyValue(element, builder, "durable-client-id");
ParsingUtils.setPropertyValue(element, builder, "durable-client-timeout");
ParsingUtils.setPropertyValue(element, builder, "keep-alive");
ParsingUtils.setPropertyValue(element, builder, "pool-name");
ParsingUtils.setPropertyValue(element, builder, "ready-for-events");
}

View File

@@ -16,10 +16,16 @@
package org.springframework.data.gemfire.util;
import java.util.Properties;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.DistributionLocator;
import com.gemstone.gemfire.management.internal.cli.util.spring.StringUtils;
/**
* DistributedSystemUtils is an abstract utility class for working with the GemFire DistributedSystem.
@@ -28,11 +34,29 @@ import com.gemstone.gemfire.internal.DistributionLocator;
* @see com.gemstone.gemfire.distributed.DistributedSystem
* @since 1.7.0
*/
@SuppressWarnings("unused")
public abstract class DistributedSystemUtils {
public static final int DEFAULT_CACHE_SERVER_PORT = CacheServer.DEFAULT_PORT;
public static final int DEFAULT_LOCATOR_PORT = DistributionLocator.DEFAULT_LOCATOR_PORT;
public static final String DURABLE_CLIENT_ID_PROPERTY_NAME = DistributionConfig.DURABLE_CLIENT_ID_NAME;
public static final String DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME = DistributionConfig.DURABLE_CLIENT_TIMEOUT_NAME;
public static Properties configureDurableClient(Properties gemfireProperties, String durableClientId, Integer durableClientTimeout) {
if (StringUtils.hasText(durableClientId)) {
Assert.notNull(gemfireProperties, "gemfireProperties must not be null");
gemfireProperties.setProperty(DURABLE_CLIENT_ID_PROPERTY_NAME, durableClientId);
if (durableClientTimeout != null) {
gemfireProperties.setProperty(DURABLE_CLIENT_TIMEOUT_PROPERTY_NAME, durableClientTimeout.toString());
}
}
return gemfireProperties;
}
@SuppressWarnings("unchecked")
public static <T extends DistributedSystem> T getDistributedSystem() {
return (T) InternalDistributedSystem.getAnyInstance();
@@ -42,4 +66,8 @@ public abstract class DistributedSystemUtils {
return (distributedSystem != null && distributedSystem.isConnected());
}
public static boolean isNotConnected(DistributedSystem distributedSystem) {
return !isConnected(distributedSystem);
}
}

View File

@@ -349,6 +349,27 @@ Defines a GemFire Client Cache instance used for creating or retrieving 'regions
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="cacheBaseType">
<xsd:attribute name="durable-client-id" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Used only for clients in a client/server installation. If set, this indicates that the client is durable
and identifies the client. The ID is used by servers to reestablish any messaging that was interrupted
by client downtime. The default value is unset. In addition, this attribute value overrides any setting
specified in gemfire.properties passed using 'properties-ref'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="durable-client-timeout" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Used only for clients in a client/server installation. Number of seconds this client can remain disconnected
from its server and have the server continue to accumulate durable events for it. The default value is 300 seconds.
In addition, this attribute value overrides any setting specified in gemfire.properties passed using 'properties-ref'.
Also, durable-client-timeout is only used if durable-client-id is set.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="keep-alive" type="xsd:string" use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[