Implements SGF-274 removing the use of temporary callback objects passed to the 'templated' execute method for each operation implementation in order to reduce the memory footprint, especially in the context of Repositories.

This commit is contained in:
John Blum
2014-05-02 14:46:42 -07:00
parent 7ef62a0c0f
commit 14754be03e
8 changed files with 881 additions and 304 deletions

View File

@@ -20,6 +20,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.util.Assert;
import com.gemstone.gemfire.GemFireCheckedException;
import com.gemstone.gemfire.GemFireException;
@@ -31,18 +32,39 @@ import com.gemstone.gemfire.cache.Region;
* Not intended to be used directly.
*
* @author Costin Leau
* @author John Blum
* @see org.springframework.beans.factory.InitializingBean
* @see com.gemstone.gemfire.cache.Region
*/
public class GemfireAccessor implements InitializingBean {
/** Logger available to subclasses */
protected final Log log = LogFactory.getLog(getClass());
private Region<?, ?> region;
private Region region;
/**
* Returns the template GemFire Cache Region.
*
* @return the GemFire Cache Region.
* @see com.gemstone.gemfire.cache.Region
*/
@SuppressWarnings("unchecked")
public <K, V> Region<K, V> getRegion() {
return region;
}
/**
* Sets the template GemFire Cache Region.
*
* @param region the GemFire Cache Region used by this template.
* @see com.gemstone.gemfire.cache.Region
*/
public void setRegion(Region<?, ?> region) {
this.region = region;
}
public void afterPropertiesSet() {
if (getRegion() == null) {
throw new IllegalArgumentException("Property 'region' is required");
}
Assert.notNull(getRegion(), "The GemFire Cache Region is required.");
}
/**
@@ -80,21 +102,4 @@ public class GemfireAccessor implements InitializingBean {
return GemfireCacheUtils.convertQueryExceptions(ex);
}
/**
* Returns the template region.
*
* @return the region
*/
public Region<?, ?> getRegion() {
return region;
}
/**
* Sets the template region.
*
* @param region the region to set
*/
public void setRegion(Region<?, ?> region) {
this.region = region;
}
}

View File

@@ -26,19 +26,25 @@ import com.gemstone.gemfire.cache.Region;
* operations on stored objects.
*
* @author Costin Leau
* @author John Blum
* @see com.gemstone.gemfire.cache.Region
*/
public interface GemfireCallback<T> {
/**
* Gets called by {@link GemfireTemplate#execute(GemfireCallback)}. Does not need to care about handling transactions
* or exceptions.
* Gets called by {@link GemfireTemplate#execute(GemfireCallback)}. Does not need to care about
* handling transactions or exceptions.
*
* Allows for returning a result object created within the callback, i.e. a domain object or a collection of domain
* objects. A thrown custom RuntimeException is treated as an application exception: It gets propagated to the caller
* of the template.
* Allows a result object created within the callback to be returned, i.e. a domain object
* or a collection of domain objects.
*
* A thrown custom RuntimeException is treated as an application exception: it gets propagated to
* the caller of the template.
*
* @param region GemFire Region
* @return a result object, or <tt>null</tt> if none
* @param region a GemFire Cache Region.
* @return a result object, or <tt>null</tt> if no result.
* @see com.gemstone.gemfire.cache.Region
*/
T doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException;
}

View File

@@ -25,97 +25,103 @@ import com.gemstone.gemfire.cache.query.SelectResults;
/**
* @author David Turanski
*
* @author John Blum
*/
public interface GemfireOperations {
public abstract boolean containsKey(Object key);
boolean containsKey(Object key);
public abstract boolean containsKeyOnServer(Object key);
boolean containsKeyOnServer(Object key);
public abstract boolean containsValue(Object value);
boolean containsValue(Object value);
public abstract boolean containsValueForKey(Object key);
boolean containsValueForKey(Object key);
public abstract <K, V> void create(K key, V value);
<K, V> void create(K key, V value);
public abstract <K, V> V get(K key);
<K, V> V get(K key);
public abstract <K, V> V put(K key, V value);
<K, V> Map<K, V> getAll(Collection<?> keys);
public abstract <K, V> V putIfAbsent(K key, V value);
<K, V> V put(K key, V value);
public abstract <K, V> V remove(K key);
<K, V> void putAll(Map<? extends K, ? extends V> map);
public abstract <K, V> V replace(K key, V value);
<K, V> V putIfAbsent(K key, V value);
public abstract <K, V> boolean replace(K key, V oldValue, V newValue);
<K, V> V replace(K key, V value);
public abstract <K, V> Map<K, V> getAll(Collection<?> keys);
<K, V> boolean replace(K key, V oldValue, V newValue);
public abstract <K, V> void putAll(Map<? extends K, ? extends V> map);
/**
* Shortcut for {@link Region#query(String)} method. Filters the values of this region using the predicate given as a string with the syntax of the WHERE clause of the query language.
* The predefined variable this may be used inside the predicate to denote the current element being filtered.
* This method evaluates the passed in where clause and returns results. It is supported on servers as well as clients.
* When executed on a client, this method always runs on the server and returns results.
* When invoking this method from the client, applications can pass in a where clause or a complete query.
* @see Region#query(String)
* @param query A query language boolean query predicate.
* @return A SelectResults containing the values of this Region that match the predicate.
*/
public abstract <E> SelectResults<E> query(String query);
<K, V> V remove(K key);
/**
* Executes a GemFire query with the given (optional) parameters and returns the result. Note this method expects the query to return multiple results; for queries that return only one
* element use {@link #findUnique(String, Object...)}.
*
* As oppose, to the {@link #query(String)} method, this method allows for more generic queries (against multiple regions even) to be executed.
*
*
* Note that the local query service is used if the region is configured as a client without any pool configuration or server connectivity - otherwise the query service on the default pool
* is being used.
*
*
* @see QueryService#newQuery(String)
* @see Query#execute(Object[])
* @see SelectResults
* @param query GemFire query
* @param params Values that are bound to parameters (such as $1) in this query.
* @param params Values that are bound to parameters (such as $1) in this query.
* @return A {@link SelectResults} instance holding the objects matching the query
* @throws InvalidDataAccessApiUsageException in case the query returns a single result (not a {@link SelectResults}).
*/
public abstract <E> SelectResults<E> find(String query, Object... params) throws InvalidDataAccessApiUsageException;
<E> SelectResults<E> find(String query, Object... params) throws InvalidDataAccessApiUsageException;
/**
* Executes a GemFire query with the given (optional) parameters and returns the result. Note this method expects the query to return a single result; for queries that return multiple
* elements use {@link #find(String, Object...)}.
*
* As oppose, to the {@link #query(String)} method, this method allows for more generic queries (against multiple regions even) to be executed.
*
*
* Note that the local query service is used if the region is configured as a client without any pool configuration or server connectivity - otherwise the query service on the default pool
* is being used.
*
*
* @see QueryService#newQuery(String)
* @see Query#execute(Object[])
* @param query GemFire query
* @param params Values that are bound to parameters (such as $1) in this query.
* @return The (single) object that represents the result of the query.
* @throws InvalidDataAccessApiUsageException in case the query returns multiple objects (through {@link SelectResults}).
* @throws InvalidDataAccessApiUsageException in case the query returns multiple objects (through {@link SelectResults}).
*/
public abstract <T> T findUnique(String query, Object... params) throws InvalidDataAccessApiUsageException;
public abstract <T> T execute(GemfireCallback<T> action) throws DataAccessException;
<T> T findUnique(String query, Object... params) throws InvalidDataAccessApiUsageException;
/**
* Execute the action specified by the given action object within a
* Region.
* @param action callback object that specifies the Gemfire action
* @param exposeNativeRegion whether to expose the native
* GemFire region to callback code
* @return a result object returned by the action, or <code>null</code>
* @throws org.springframework.dao.DataAccessException in case of GemFire errors
* Shortcut for {@link Region#query(String)} method. Filters the values of this region using the predicate given as a string with the syntax of the WHERE clause of the query language.
* The predefined variable this may be used inside the predicate to denote the current element being filtered.
* This method evaluates the passed in where clause and returns results. It is supported on servers as well as clients.
* When executed on a client, this method always runs on the server and returns results.
* When invoking this method from the client, applications can pass in a where clause or a complete query.
* @see Region#query(String)
* @param query A query language boolean query predicate.
* @return A SelectResults containing the values of this Region that match the predicate.
*/
public abstract <T> T execute(GemfireCallback<T> action, boolean exposeNativeRegion) throws DataAccessException;
<E> SelectResults<E> query(String query);
/**
* Execute the action specified by the given action object within a Region.
*
* @param action callback object that specifies the Gemfire action to execute.
* @return a result object returned by the action, or <code>null</code>.
* @throws org.springframework.dao.DataAccessException in case of GemFire errors.
*/
<T> T execute(GemfireCallback<T> action) throws DataAccessException;
/**
* Execute the action specified by the given action object within a Region.
*
* @param action callback object that specifies the Gemfire action to execute.
* @param exposeNativeRegion whether to expose the native GemFire region to callback code.
* @return a result object returned by the action, or <code>null</code>.
* @throws org.springframework.dao.DataAccessException in case of GemFire errors.
*/
<T> T execute(GemfireCallback<T> action, boolean exposeNativeRegion) throws DataAccessException;
}

View File

@@ -44,7 +44,6 @@ import com.gemstone.gemfire.internal.cache.LocalRegion;
* Helper class that simplifies GemFire data access code and converts {@link GemFireCheckedException} and
* {@link GemFireException} into Spring {@link DataAccessException}, following the <tt>org.springframework.dao</tt>
* exception hierarchy.
*
*
* The central method is <tt>execute</tt>, supporting GemFire access code implementing the GemfireCallback interface.
* It provides dedicated handling such that neither the GemfireCallback implementation nor the calling code needs to
@@ -52,9 +51,18 @@ import com.gemstone.gemfire.internal.cache.LocalRegion;
* Typically used to implement data access or business logic services that use GemFire within their implementation but
* are GemFire-agnostic in their interface. The latter or code calling the latter only have to deal with business
* objects, query objects, and <tt>org.springframework.dao</tt> exceptions.
*
*
* @author Costin Leau
* @author John Blum
* @see java.util.Map
* @see org.springframework.data.gemfire.GemfireAccessor
* @see org.springframework.data.gemfire.GemfireOperations
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.query.Query
* @see com.gemstone.gemfire.cache.query.QueryService
* @see com.gemstone.gemfire.cache.query.SelectResults
*/
@SuppressWarnings("unused")
public class GemfireTemplate extends GemfireAccessor implements GemfireOperations {
private boolean exposeNativeRegion = false;
@@ -101,11 +109,7 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public boolean containsKey(final Object key) {
return execute(new GemfireCallback<Boolean>() {
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
return region.containsKey(key);
}
});
return getRegion().containsKey(key);
}
/* (non-Javadoc)
@@ -113,11 +117,7 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public boolean containsKeyOnServer(final Object key) {
return execute(new GemfireCallback<Boolean>() {
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
return region.containsKeyOnServer(key);
}
});
return getRegion().containsKeyOnServer(key);
}
/* (non-Javadoc)
@@ -125,11 +125,7 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public boolean containsValue(final Object value) {
return execute(new GemfireCallback<Boolean>() {
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
return region.containsValue(value);
}
});
return getRegion().containsValue(value);
}
/* (non-Javadoc)
@@ -137,11 +133,7 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public boolean containsValueForKey(final Object key) {
return execute(new GemfireCallback<Boolean>() {
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
return region.containsValueForKey(key);
}
});
return getRegion().containsValueForKey(key);
}
/* (non-Javadoc)
@@ -149,13 +141,12 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public <K, V> void create(final K key, final V value) {
execute(new GemfireCallback<Object>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
region.create(key, value);
return null;
}
});
try {
getRegion().create(key, value);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
@@ -163,77 +154,12 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public <K, V> V get(final K key) {
return execute(new GemfireCallback<V>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.get(key);
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#put(K, V)
*/
@Override
public <K, V> V put(final K key, final V value) {
return execute(new GemfireCallback<V>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.put(key, value);
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#putIfAbsent(K, V)
*/
@Override
public <K, V> V putIfAbsent(final K key, final V value) {
return execute(new GemfireCallback<V>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.putIfAbsent(key, value);
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#remove(K)
*/
@Override
public <K, V> V remove(final K key) {
return execute(new GemfireCallback<V>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.remove(key);
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#replace(K, V)
*/
@Override
public <K, V> V replace(final K key, final V value) {
return execute(new GemfireCallback<V>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.replace(key, value);
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#replace(K, V, V)
*/
@Override
public <K, V> boolean replace(final K key, final V oldValue, final V newValue) {
return execute(new GemfireCallback<Boolean>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.replace(key, oldValue, newValue);
}
});
try {
return this.<K, V>getRegion().get(key);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
@@ -241,12 +167,25 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public <K, V> Map<K, V> getAll(final Collection<?> keys) {
return execute(new GemfireCallback<Map<K, V>>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public Map<K, V> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (Map<K, V>) region.getAll(keys);
}
});
try {
return this.<K, V>getRegion().getAll(keys);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#put(K, V)
*/
@Override
public <K, V> V put(final K key, final V value) {
try {
return this.<K, V>getRegion().put(key, value);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
@@ -254,13 +193,64 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public <K, V> void putAll(final Map<? extends K, ? extends V> map) {
execute(new GemfireCallback<Object>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
region.putAll(map);
return null;
}
});
try {
this.<K, V>getRegion().putAll(map);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#putIfAbsent(K, V)
*/
@Override
public <K, V> V putIfAbsent(final K key, final V value) {
try {
return this.<K, V>getRegion().putIfAbsent(key, value);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#remove(K)
*/
@Override
public <K, V> V remove(final K key) {
try {
return this.<K, V>getRegion().remove(key);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#replace(K, V)
*/
@Override
public <K, V> V replace(final K key, final V value) {
try {
return this.<K, V>getRegion().replace(key, value);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#replace(K, V, V)
*/
@Override
public <K, V> boolean replace(final K key, final V oldValue, final V newValue) {
try {
return this.<K, V>getRegion().replace(key, oldValue, newValue);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
}
/* (non-Javadoc)
@@ -268,78 +258,164 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
*/
@Override
public <E> SelectResults<E> query(final String query) {
return execute(new GemfireCallback<SelectResults<E>>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.query(query);
try {
return this.getRegion().query(query);
}
catch (IndexInvalidException ex) {
throw convertGemFireQueryException(ex);
}
catch (QueryInvalidException ex) {
throw convertGemFireQueryException(ex);
}
catch (GemFireCheckedException e) {
throw convertGemFireAccessException(e);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
catch (RuntimeException ex) {
// test for CqInvalidException (removed in 6.5)
if (GemfireCacheUtils.isCqInvalidException(ex)) {
throw GemfireCacheUtils.convertCqInvalidException(ex);
}
});
// callback code threw application exception
throw ex;
}
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#find(java.lang.String, java.lang.Object)
*/
@Override
public <E> SelectResults<E> find(final String query, final Object... params)
throws InvalidDataAccessApiUsageException {
return execute(new GemfireCallback<SelectResults<E>>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
QueryService queryService = lookupQueryService(region);
Query q = queryService.newQuery(query);
Object result = q.execute(params);
if (result instanceof SelectResults) {
return (SelectResults<E>) result;
}
throw new InvalidDataAccessApiUsageException(
"Result object returned from GemfireCallback isn't a SelectResult: [" + result + "]");
@SuppressWarnings("unchecked")
public <E> SelectResults<E> find(final String queryString, final Object... params) throws InvalidDataAccessApiUsageException {
try {
QueryService queryService = lookupQueryService(getRegion());
Query query = queryService.newQuery(queryString);
Object result = query.execute(params);
if (result instanceof SelectResults) {
return (SelectResults<E>) result;
}
});
else {
throw new InvalidDataAccessApiUsageException(
"Result object returned from GemfireCallback isn't a SelectResult: [" + result + "]");
}
}
catch (IndexInvalidException ex) {
throw convertGemFireQueryException(ex);
}
catch (QueryInvalidException ex) {
throw convertGemFireQueryException(ex);
}
catch (GemFireCheckedException e) {
throw convertGemFireAccessException(e);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
catch (RuntimeException ex) {
// test for CqInvalidException (removed in 6.5)
if (GemfireCacheUtils.isCqInvalidException(ex)) {
throw GemfireCacheUtils.convertCqInvalidException(ex);
}
// callback code threw application exception
throw ex;
}
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#findUnique(java.lang.String, java.lang.Object)
*/
@Override
public <T> T findUnique(final String query, final Object... params) throws InvalidDataAccessApiUsageException {
return execute(new GemfireCallback<T>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
public T doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
QueryService queryService = lookupQueryService(region);
Query q = queryService.newQuery(query);
Object result = q.execute(params);
if (result instanceof SelectResults) {
SelectResults<T> selectResults = (SelectResults<T>)result;
if (selectResults.asList().size() == 1) {
result = selectResults.iterator().next();
} else {
throw new InvalidDataAccessApiUsageException(
"Result object returned from GemfireCallback isn't unique: [" + result + "]");
}
}
return (T) result;
}
});
}
@SuppressWarnings("unchecked")
public <T> T findUnique(final String queryString, final Object... params) throws InvalidDataAccessApiUsageException {
try {
QueryService queryService = lookupQueryService(getRegion());
Query query = queryService.newQuery(queryString);
Object result = query.execute(params);
if (result instanceof SelectResults) {
SelectResults<T> selectResults = (SelectResults<T>) result;
if (selectResults.asList().size() == 1) {
result = selectResults.iterator().next();
}
else {
throw new InvalidDataAccessApiUsageException(String.format(
"The result returned from query (%1$s) is not unique: (%2$s).", queryString, result));
}
}
return (T) result;
}
catch (IndexInvalidException ex) {
throw convertGemFireQueryException(ex);
}
catch (QueryInvalidException ex) {
throw convertGemFireQueryException(ex);
}
catch (GemFireCheckedException e) {
throw convertGemFireAccessException(e);
}
catch (GemFireException e) {
throw convertGemFireAccessException(e);
}
catch (RuntimeException ex) {
// test for CqInvalidException (removed in 6.5)
if (GemfireCacheUtils.isCqInvalidException(ex)) {
throw GemfireCacheUtils.convertCqInvalidException(ex);
}
// callback code threw application exception
throw ex;
}
}
/**
* Returns the query service used by the template in its find methods.
*
* @param region region to find the local query service from
* @return query service to use, local or generic
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.Region#getRegionService()
* @see com.gemstone.gemfire.cache.RegionService#getQueryService()
* @see com.gemstone.gemfire.cache.client.ClientCache#getLocalQueryService()
*/
protected QueryService lookupQueryService(Region<?, ?> region) {
if (region.getRegionService() instanceof ClientCache
&& (region instanceof LocalRegion && !((LocalRegion) region).hasServerProxy())
&& Scope.LOCAL.equals(region.getAttributes().getScope())) {
return ((ClientCache) region.getRegionService()).getLocalQueryService();
}
return region.getRegionService().getQueryService();
protected QueryService lookupQueryService(final Region<?, ?> region) {
return (requiresLocalQueryService(region) ? ((ClientCache) region.getRegionService()).getLocalQueryService()
: region.getRegionService().getQueryService());
}
/*
* (non-Javadoc)
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.internal.cache.LocalRegion
*/
/* package-private */ boolean isLocalWithNoServerProxy(final Region<?, ?> region) {
return (region instanceof LocalRegion && !((LocalRegion) region).hasServerProxy());
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see #isLocalWithNoServerProxy(:Region)
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.RegionAttributes
* @see com.gemstone.gemfire.cache.RegionAttributes#getScope()
* @see com.gemstone.gemfire.cache.Scope
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.internal.cache.LocalRegion
* @see com.gemstone.gemfire.internal.cache.LocalRegion#hasServerProxy()
*/
private boolean requiresLocalQueryService(final Region<?, ?> region) {
return (region.getRegionService() instanceof ClientCache && isLocalWithNoServerProxy(region)
&& Scope.LOCAL.equals(region.getAttributes().getScope()));
}
/*
* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#execute(org.springframework.data.gemfire.GemfireCallback)
*/
@Override
@@ -347,7 +423,8 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
return execute(action, isExposeNativeRegion());
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.gemfire.GemfireOperations#execute(org.springframework.data.gemfire.GemfireCallback, boolean)
*/
@Override
@@ -355,21 +432,26 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
Assert.notNull(action, "Callback object must not be null");
try {
Region<?, ?> regionToExpose = (exposeNativeRegion ? getRegion() : regionProxy);
T result = action.doInGemfire(regionToExpose);
return result;
} catch (IndexInvalidException ex) {
return action.doInGemfire(regionToExpose);
}
catch (IndexInvalidException ex) {
throw convertGemFireQueryException(ex);
} catch (QueryInvalidException ex) {
}
catch (QueryInvalidException ex) {
throw convertGemFireQueryException(ex);
} catch (GemFireCheckedException ex) {
}
catch (GemFireCheckedException ex) {
throw convertGemFireAccessException(ex);
} catch (GemFireException ex) {
}
catch (GemFireException ex) {
throw convertGemFireAccessException(ex);
} catch (RuntimeException ex) {
// try first the CqInvalidException (removed in 6.5)
}
catch (RuntimeException ex) {
// test for CqInvalidException (removed in 6.5)
if (GemfireCacheUtils.isCqInvalidException(ex)) {
throw GemfireCacheUtils.convertCqInvalidException(ex);
}
// callback code threw application exception
throw ex;
}
@@ -386,51 +468,49 @@ public class GemfireTemplate extends GemfireAccessor implements GemfireOperation
* @see #execute(GemfireCallback, boolean)
*/
@SuppressWarnings("unchecked")
protected <K, V> Region<K, V> createRegionProxy(Region<K, V> region) {
Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(region.getClass(), getClass().getClassLoader());
return (Region<K, V>) Proxy.newProxyInstance(region.getClass().getClassLoader(), ifcs,
new CloseSuppressingInvocationHandler(region));
protected <K, V> Region<K, V> createRegionProxy(final Region<K, V> region) {
return (Region<K, V>) Proxy.newProxyInstance(region.getClass().getClassLoader(),
ClassUtils.getAllInterfacesForClass(region.getClass(), getClass().getClassLoader()),
new RegionCloseSuppressingInvocationHandler(region));
}
//-------------------------------------------------------------------------
// Convenience methods for load, save, delete
//-------------------------------------------------------------------------
/**
* Invocation handler that suppresses close calls on GemFire Regions.
* @see Region#close()
* InvocationHandler that suppresses close calls on GemFire Cache Regions.
*
* @see com.gemstone.gemfire.cache.Region#close()
* @see java.lang.reflect.InvocationHandler
*/
private static class CloseSuppressingInvocationHandler implements InvocationHandler {
private static class RegionCloseSuppressingInvocationHandler implements InvocationHandler {
private final Region<?, ?> target;
public CloseSuppressingInvocationHandler(Region<?, ?> target) {
public RegionCloseSuppressingInvocationHandler(final Region<?, ?> target) {
Assert.notNull(target, "The Region to target must not be null.");
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Region interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
// only consider equal when proxies are identical
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of region proxy.
// use hashCode of Region proxy
return System.identityHashCode(proxy);
}
else if (method.getName().equals("close")) {
// Handle close method: suppress, not valid.
// suppress Region.close() method call
return null;
}
// Invoke method on target Region
try {
Object retVal = method.invoke(this.target, args);
return retVal;
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
else {
try {
return method.invoke(this.target, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}
}