org.springframework.data.gemfire.client.PoolFactoryBean Maven / Gradle / Ivy
/*
* 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 java.net.InetSocketAddress;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.support.ConnectionEndpointList;
import org.springframework.data.gemfire.util.DistributedSystemUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolFactory;
import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.distributed.DistributedSystem;
/**
* FactoryBean for easy declaration and configuration of a GemFire {@link Pool}. If a new {@link Pool} is created,
* its lifecycle is bound to that of this declaring factory.
*
* Note, if a {@link Pool} having the configured name already exists, then the existing {@link Pool} will be returned
* as is without any modifications and its lifecycle will be unaffected by this factory.
*
* @author Costin Leau
* @author John Blum
* @see java.net.InetSocketAddress
* @see org.springframework.beans.factory.BeanNameAware
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
* @see com.gemstone.gemfire.cache.client.Pool
* @see com.gemstone.gemfire.cache.client.PoolFactory
* @see com.gemstone.gemfire.cache.client.PoolManager
*/
@SuppressWarnings("unused")
public class PoolFactoryBean implements FactoryBean, InitializingBean, DisposableBean,
BeanNameAware, BeanFactoryAware {
protected static final int DEFAULT_LOCATOR_PORT = DistributedSystemUtils.DEFAULT_LOCATOR_PORT;
protected static final int DEFAULT_SERVER_PORT = DistributedSystemUtils.DEFAULT_CACHE_SERVER_PORT;
private static final Log log = LogFactory.getLog(PoolFactoryBean.class);
// indicates whether the Pool has been created internally (by this FactoryBean) or not
volatile boolean springBasedPool = true;
private BeanFactory beanFactory;
private ConnectionEndpointList locators = new ConnectionEndpointList();
private ConnectionEndpointList servers = new ConnectionEndpointList();
private volatile Pool pool;
private String beanName;
private String name;
// GemFire Pool Configuration Settings
private boolean keepAlive = false;
private boolean multiUserAuthentication = PoolFactory.DEFAULT_MULTIUSER_AUTHENTICATION;
private boolean prSingleHopEnabled = PoolFactory.DEFAULT_PR_SINGLE_HOP_ENABLED;
private boolean subscriptionEnabled = PoolFactory.DEFAULT_SUBSCRIPTION_ENABLED;
private boolean threadLocalConnections = PoolFactory.DEFAULT_THREAD_LOCAL_CONNECTIONS;
private int freeConnectionTimeout = PoolFactory.DEFAULT_FREE_CONNECTION_TIMEOUT;
private int loadConditioningInterval = PoolFactory.DEFAULT_LOAD_CONDITIONING_INTERVAL;
private int maxConnections = PoolFactory.DEFAULT_MAX_CONNECTIONS;
private int minConnections = PoolFactory.DEFAULT_MIN_CONNECTIONS;
private int readTimeout = PoolFactory.DEFAULT_READ_TIMEOUT;
private int retryAttempts = PoolFactory.DEFAULT_RETRY_ATTEMPTS;
private int socketBufferSize = PoolFactory.DEFAULT_SOCKET_BUFFER_SIZE;
private int statisticInterval = PoolFactory.DEFAULT_STATISTIC_INTERVAL;
private int subscriptionAckInterval = PoolFactory.DEFAULT_SUBSCRIPTION_ACK_INTERVAL;
private int subscriptionMessageTrackingTimeout = PoolFactory.DEFAULT_SUBSCRIPTION_MESSAGE_TRACKING_TIMEOUT;
private int subscriptionRedundancy = PoolFactory.DEFAULT_SUBSCRIPTION_REDUNDANCY;
private long idleTimeout = PoolFactory.DEFAULT_IDLE_TIMEOUT;
private long pingInterval = PoolFactory.DEFAULT_PING_INTERVAL;
private String serverGroup = PoolFactory.DEFAULT_SERVER_GROUP;
/**
* Constructs and initializes a GemFire {@link Pool}.
*
* @throws Exception if the {@link Pool} creation and initialization fails.
* @see com.gemstone.gemfire.cache.client.Pool
* @see com.gemstone.gemfire.cache.client.PoolFactory
* @see com.gemstone.gemfire.cache.client.PoolManager
* @see #createPoolFactory()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasText(name)) {
Assert.hasText(beanName, "Pool 'name' is required");
name = beanName;
}
// check for an existing, configured Pool with name first
Pool existingPool = PoolManager.find(name);
if (existingPool != null) {
if (log.isDebugEnabled()) {
log.debug(String.format("A Pool with name [%1$s] already exists; using existing Pool.", name));
}
springBasedPool = false;
pool = existingPool;
}
else {
if (log.isDebugEnabled()) {
log.debug(String.format("No Pool with name [%1$s] was found. Creating new Pool.", name));
}
springBasedPool = true;
}
}
/**
* Destroys the GemFire {@link Pool} if created by this {@link PoolFactoryBean} and releases all system resources
* used by the {@link Pool}.
*
* @throws Exception if the {@link Pool} destruction caused an error.
* @see DisposableBean#destroy()
*/
@Override
public void destroy() throws Exception {
if (springBasedPool && pool != null && !pool.isDestroyed()) {
pool.releaseThreadLocalConnection();
pool.destroy(keepAlive);
pool = null;
if (log.isDebugEnabled()) {
log.debug(String.format("Destroyed Pool [%1$s]", name));
}
}
}
/* (non-Javadoc) */
@Override
public Pool getObject() throws Exception {
if (pool == null) {
eagerlyInitializeClientCacheIfNotPresent();
PoolFactory poolFactory = createPoolFactory();
poolFactory.setFreeConnectionTimeout(freeConnectionTimeout);
poolFactory.setIdleTimeout(idleTimeout);
poolFactory.setLoadConditioningInterval(loadConditioningInterval);
poolFactory.setMaxConnections(maxConnections);
poolFactory.setMinConnections(minConnections);
poolFactory.setMultiuserAuthentication(multiUserAuthentication);
poolFactory.setPingInterval(pingInterval);
poolFactory.setPRSingleHopEnabled(prSingleHopEnabled);
poolFactory.setReadTimeout(readTimeout);
poolFactory.setRetryAttempts(retryAttempts);
poolFactory.setServerGroup(serverGroup);
poolFactory.setSocketBufferSize(socketBufferSize);
poolFactory.setStatisticInterval(statisticInterval);
poolFactory.setSubscriptionAckInterval(subscriptionAckInterval);
poolFactory.setSubscriptionEnabled(subscriptionEnabled);
poolFactory.setSubscriptionMessageTrackingTimeout(subscriptionMessageTrackingTimeout);
poolFactory.setSubscriptionRedundancy(subscriptionRedundancy);
poolFactory.setThreadLocalConnections(threadLocalConnections);
for (ConnectionEndpoint locator : locators) {
poolFactory.addLocator(locator.getHost(), locator.getPort());
}
for (ConnectionEndpoint server : servers) {
poolFactory.addServer(server.getHost(), server.getPort());
}
pool = poolFactory.create(name);
}
return pool;
}
/**
* Attempts to eagerly initialize the GemFire {@link ClientCache} if not already present so that the single
* {@link com.gemstone.gemfire.distributed.DistributedSystem} will exists, which is required to create
* a {@link Pool} instance.
*
* @see org.springframework.beans.factory.BeanFactory#getBean(Class)
* @see com.gemstone.gemfire.cache.client.ClientCache
*/
void eagerlyInitializeClientCacheIfNotPresent() {
if (!isDistributedSystemPresent()) {
getBeanFactory().getBean(ClientCache.class);
}
}
/**
* Determines whether the GemFire DistributedSystem exists yet or not.
*
* @return a boolean value indicating whether the single, GemFire DistributedSystem has been created already.
* @see org.springframework.data.gemfire.GemfireUtils#getDistributedSystem()
* @see org.springframework.data.gemfire.GemfireUtils#isConnected(DistributedSystem)
* @see com.gemstone.gemfire.distributed.DistributedSystem
*/
boolean isDistributedSystemPresent() {
return GemfireUtils.isConnected(GemfireUtils.getDistributedSystem());
}
/**
* Creates an instance of the GemFire {@link PoolFactory} interface to construct, configure and initialize
* a GemFire {@link Pool}.
*
* @return a {@link PoolFactory} implementation to create a {@link Pool}.
* @see com.gemstone.gemfire.cache.client.PoolManager#createFactory()
* @see com.gemstone.gemfire.cache.client.PoolFactory
*/
protected PoolFactory createPoolFactory() {
return PoolManager.createFactory();
}
/* (non-Javadoc) */
@Override
public Class getObjectType() {
return (pool != null ? pool.getClass() : Pool.class);
}
/* (non-Javadoc) */
@Override
public boolean isSingleton() {
return true;
}
/* (non-Javadoc) */
public void addLocators(ConnectionEndpoint... locators) {
this.locators.add(locators);
}
/* (non-Javadoc) */
public void addLocators(Iterable locators) {
this.locators.add(locators);
}
/* (non-Javadoc) */
public void addServers(ConnectionEndpoint... servers) {
this.servers.add(servers);
}
/* (non-Javadoc) */
public void addServers(Iterable servers) {
this.servers.add(servers);
}
/* (non-Javadoc) */
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
/* (non-Javadoc) */
protected BeanFactory getBeanFactory() {
return beanFactory;
}
/* (non-Javadoc) */
public void setBeanName(String name) {
this.beanName = name;
}
/* (non-Javadoc) */
public void setName(String name) {
this.name = name;
}
/* (non-Javadoc) */
String getName() {
return name;
}
/* (non-Javadoc) */
public void setPool(Pool pool) {
this.pool = pool;
}
/* (non-Javadoc) */
public Pool getPool() {
return (pool != null ? pool : new PoolAdapter() {
@Override
public boolean isDestroyed() {
Pool pool = PoolFactoryBean.this.pool;
return (pool != null && pool.isDestroyed());
}
@Override
public int getFreeConnectionTimeout() {
return PoolFactoryBean.this.freeConnectionTimeout;
}
@Override
public long getIdleTimeout() {
return PoolFactoryBean.this.idleTimeout;
}
@Override
public int getLoadConditioningInterval() {
return PoolFactoryBean.this.loadConditioningInterval;
}
@Override
public List getLocators() {
return PoolFactoryBean.this.locators.toInetSocketAddresses();
}
@Override
public int getMaxConnections() {
return PoolFactoryBean.this.maxConnections;
}
@Override
public int getMinConnections() {
return PoolFactoryBean.this.minConnections;
}
@Override
public boolean getMultiuserAuthentication() {
return PoolFactoryBean.this.multiUserAuthentication;
}
@Override
public String getName() {
String name = PoolFactoryBean.this.name;
name = (StringUtils.hasText(name) ? name : PoolFactoryBean.this.beanName);
return name;
}
@Override
public int getPendingEventCount() {
Pool pool = PoolFactoryBean.this.pool;
if (pool != null) {
return pool.getPendingEventCount();
}
throw new IllegalStateException("The Pool is not initialized");
}
@Override
public long getPingInterval() {
return PoolFactoryBean.this.pingInterval;
}
@Override
public boolean getPRSingleHopEnabled() {
return PoolFactoryBean.this.prSingleHopEnabled;
}
@Override
public QueryService getQueryService() {
Pool pool = PoolFactoryBean.this.pool;
if (pool != null) {
return pool.getQueryService();
}
throw new IllegalStateException("The Pool is not initialized");
}
@Override
public int getReadTimeout() {
return PoolFactoryBean.this.readTimeout;
}
@Override
public int getRetryAttempts() {
return PoolFactoryBean.this.retryAttempts;
}
@Override
public String getServerGroup() {
return PoolFactoryBean.this.serverGroup;
}
@Override
public List getServers() {
return PoolFactoryBean.this.servers.toInetSocketAddresses();
}
@Override
public int getSocketBufferSize() {
return PoolFactoryBean.this.socketBufferSize;
}
@Override
public int getStatisticInterval() {
return PoolFactoryBean.this.statisticInterval;
}
@Override
public int getSubscriptionAckInterval() {
return PoolFactoryBean.this.subscriptionAckInterval;
}
@Override
public boolean getSubscriptionEnabled() {
return PoolFactoryBean.this.subscriptionEnabled;
}
@Override
public int getSubscriptionMessageTrackingTimeout() {
return PoolFactoryBean.this.subscriptionMessageTrackingTimeout;
}
@Override
public int getSubscriptionRedundancy() {
return PoolFactoryBean.this.subscriptionRedundancy;
}
@Override
public boolean getThreadLocalConnections() {
return PoolFactoryBean.this.threadLocalConnections;
}
@Override
public void destroy() {
destroy(false);
}
@Override
public void destroy(final boolean keepAlive) {
try {
PoolFactoryBean.this.destroy();
}
catch (Exception ignore) {
Pool pool = PoolFactoryBean.this.pool;
if (pool != null) {
pool.destroy(keepAlive);
}
}
}
@Override
public void releaseThreadLocalConnection() {
Pool pool = PoolFactoryBean.this.pool;
if (pool != null) {
pool.releaseThreadLocalConnection();
}
else {
throw new IllegalStateException("The Pool is not initialized");
}
}
});
}
/* (non-Javadoc) */
public void setFreeConnectionTimeout(int freeConnectionTimeout) {
this.freeConnectionTimeout = freeConnectionTimeout;
}
/* (non-Javadoc) */
public void setIdleTimeout(long idleTimeout) {
this.idleTimeout = idleTimeout;
}
/* (non-Javadoc) */
public void setKeepAlive(boolean keepAlive) {
this.keepAlive = keepAlive;
}
/* (non-Javadoc) */
public void setLoadConditioningInterval(int loadConditioningInterval) {
this.loadConditioningInterval = loadConditioningInterval;
}
/* (non-Javadoc) */
public void setLocators(ConnectionEndpoint[] connectionEndpoints) {
setLocators(ConnectionEndpointList.from(connectionEndpoints));
}
/* (non-Javadoc) */
public void setLocators(Iterable connectionEndpoints) {
getLocators().clear();
getLocators().add(connectionEndpoints);
}
/* (non-Javadoc) */
ConnectionEndpointList getLocators() {
return locators;
}
/* (non-Javadoc) */
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
/* (non-Javadoc) */
public void setMinConnections(int minConnections) {
this.minConnections = minConnections;
}
/* (non-Javadoc) */
public void setMultiUserAuthentication(boolean multiUserAuthentication) {
this.multiUserAuthentication = multiUserAuthentication;
}
/* (non-Javadoc) */
public void setPingInterval(long pingInterval) {
this.pingInterval = pingInterval;
}
/* (non-Javadoc) */
public void setPrSingleHopEnabled(boolean prSingleHopEnabled) {
this.prSingleHopEnabled = prSingleHopEnabled;
}
/* (non-Javadoc) */
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
/* (non-Javadoc) */
public void setRetryAttempts(int retryAttempts) {
this.retryAttempts = retryAttempts;
}
/* (non-Javadoc) */
public void setServerGroup(String serverGroup) {
this.serverGroup = serverGroup;
}
/* (non-Javadoc) */
public void setServers(ConnectionEndpoint[] connectionEndpoints) {
setServers(ConnectionEndpointList.from(connectionEndpoints));
}
/* (non-Javadoc) */
public void setServers(Iterable connectionEndpoints) {
getServers().clear();
getServers().add(connectionEndpoints);
}
/* (non-Javadoc) */
ConnectionEndpointList getServers() {
return servers;
}
/* (non-Javadoc) */
public void setSocketBufferSize(int socketBufferSize) {
this.socketBufferSize = socketBufferSize;
}
/* (non-Javadoc) */
public void setStatisticInterval(int statisticInterval) {
this.statisticInterval = statisticInterval;
}
/* (non-Javadoc) */
public void setSubscriptionAckInterval(int subscriptionAckInterval) {
this.subscriptionAckInterval = subscriptionAckInterval;
}
/* (non-Javadoc) */
public void setSubscriptionEnabled(boolean subscriptionEnabled) {
this.subscriptionEnabled = subscriptionEnabled;
}
/* (non-Javadoc) */
public void setSubscriptionMessageTrackingTimeout(int subscriptionMessageTrackingTimeout) {
this.subscriptionMessageTrackingTimeout = subscriptionMessageTrackingTimeout;
}
/* (non-Javadoc) */
public void setSubscriptionRedundancy(int subscriptionRedundancy) {
this.subscriptionRedundancy = subscriptionRedundancy;
}
/* (non-Javadoc) */
public void setThreadLocalConnections(boolean threadLocalConnections) {
this.threadLocalConnections = threadLocalConnections;
}
}