SGF-173. Added NoResult methods to FunctionTemplate and checked for FunctionExecution exception related to Function.hasResult() = false
This commit is contained in:
@@ -35,30 +35,33 @@ import com.gemstone.gemfire.cache.execute.ResultCollector;
|
||||
*/
|
||||
|
||||
abstract class AbstractFunctionExecution {
|
||||
|
||||
private final static String NO_RESULT_MESSAGE = "Cannot return any result as the Function#hasResult() is false";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
|
||||
private volatile ResultCollector<?, ?> resultCollector;
|
||||
private Object[] args;
|
||||
private Function function;
|
||||
private String functionId;
|
||||
private Function function;
|
||||
private String functionId;
|
||||
private long timeout;
|
||||
|
||||
public AbstractFunctionExecution(Function function, Object... args) {
|
||||
Assert.notNull(function,"function cannot be null");
|
||||
this.function = function;
|
||||
Assert.notNull(function, "function cannot be null");
|
||||
this.function = function;
|
||||
this.functionId = function.getId();
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
|
||||
public AbstractFunctionExecution(String functionId, Object... args) {
|
||||
Assert.isTrue(StringUtils.hasLength(functionId),"functionId cannot be null or empty");
|
||||
this.functionId = functionId;
|
||||
Assert.isTrue(StringUtils.hasLength(functionId), "functionId cannot be null or empty");
|
||||
this.functionId = functionId;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
|
||||
AbstractFunctionExecution() {
|
||||
}
|
||||
|
||||
|
||||
ResultCollector<?, ?> getCollector() {
|
||||
return resultCollector;
|
||||
}
|
||||
@@ -70,17 +73,21 @@ abstract class AbstractFunctionExecution {
|
||||
String getFunctionId() {
|
||||
return functionId;
|
||||
}
|
||||
|
||||
|
||||
Function getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
|
||||
long getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
}
|
||||
|
||||
<T> Iterable<T> execute() {
|
||||
return execute(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> Iterable<T> execute(Boolean returnResult) {
|
||||
Execution execution = this.getExecution();
|
||||
if (getKeys() != null) {
|
||||
execution = execution.withFilter(getKeys());
|
||||
@@ -88,107 +95,119 @@ abstract class AbstractFunctionExecution {
|
||||
if (getCollector() != null) {
|
||||
execution = execution.withCollector(getCollector());
|
||||
}
|
||||
|
||||
ResultCollector<?,?> resultCollector = null;
|
||||
|
||||
|
||||
ResultCollector<?, ?> resultCollector = null;
|
||||
|
||||
execution = execution.withArgs(getArgs());
|
||||
|
||||
if (isRegisteredFunction()){
|
||||
|
||||
resultCollector = (ResultCollector<?,?>) execution.execute(functionId);
|
||||
|
||||
if (isRegisteredFunction()) {
|
||||
resultCollector = (ResultCollector<?, ?>) execution.execute(functionId);
|
||||
} else {
|
||||
resultCollector = (ResultCollector<?,?>) execution.execute(function);
|
||||
resultCollector = (ResultCollector<?, ?>) execution.execute(function);
|
||||
if (!function.hasResult()) {
|
||||
return (Iterable<T>) null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!returnResult) {
|
||||
return (Iterable<T>) null;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("using ResultsCollector:" + resultCollector.getClass().getName());
|
||||
}
|
||||
|
||||
|
||||
Iterable<T> results = null;
|
||||
|
||||
if (this.timeout > 0 ){
|
||||
try {
|
||||
results= (Iterable<T>)resultCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
|
||||
|
||||
try {
|
||||
if (this.timeout > 0) {
|
||||
try {
|
||||
results = (Iterable<T>) resultCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
|
||||
} catch (FunctionException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
|
||||
results = (Iterable<T>) resultCollector.getResult();
|
||||
}
|
||||
catch (FunctionException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
return replaceSingletonNullCollectionWithEmptyList(results);
|
||||
|
||||
} catch (FunctionException e) {
|
||||
//TODO: Come up with a better way to determine that the function should not return a result;
|
||||
if (!e.getMessage().equals(NO_RESULT_MESSAGE)) {
|
||||
throw e;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
|
||||
results = (Iterable<T>) resultCollector.getResult();
|
||||
}
|
||||
|
||||
return replaceSingletonNullCollectionWithEmptyList(results);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
<T> T executeAndExtract() {
|
||||
Iterable<T> results = this.execute();
|
||||
if (results == null || !results.iterator().hasNext()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return results.iterator().next();
|
||||
}
|
||||
|
||||
|
||||
protected abstract Execution getExecution();
|
||||
|
||||
|
||||
protected AbstractFunctionExecution setFunctionId(String functionId) {
|
||||
this.functionId = functionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
protected AbstractFunctionExecution setFunction(Function function) {
|
||||
this.function = function;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
protected AbstractFunctionExecution setArgs(Object... args) {
|
||||
this.args = args;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
protected Set<?> getKeys() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected AbstractFunctionExecution setTimeout(long timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected AbstractFunctionExecution setResultCollector(ResultCollector<?,?> resultCollector) {
|
||||
|
||||
protected AbstractFunctionExecution setResultCollector(ResultCollector<?, ?> resultCollector) {
|
||||
this.resultCollector = resultCollector;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private boolean isRegisteredFunction() {
|
||||
return function == null;
|
||||
return function == null;
|
||||
}
|
||||
|
||||
|
||||
private <T> Iterable<T> replaceSingletonNullCollectionWithEmptyList(Iterable<T> results) {
|
||||
if (results == null) {
|
||||
return results;
|
||||
}
|
||||
Iterator<T> it = results.iterator();
|
||||
|
||||
|
||||
if (!it.hasNext()) {
|
||||
return results;
|
||||
}
|
||||
|
||||
if (it.next()==null && !it.hasNext()) {
|
||||
|
||||
if (it.next() == null && !it.hasNext()) {
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
|
||||
|
||||
return results;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -56,6 +56,14 @@ abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
|
||||
.setFunctionId(functionId);
|
||||
return execute(functionExecution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeWithNoResult(String functionId, Object... args) {
|
||||
AbstractFunctionExecution functionExecution = getFunctionExecution()
|
||||
.setArgs(args)
|
||||
.setFunctionId(functionId);
|
||||
execute(functionExecution,false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T executeAndExtract(String functionId, Object... args) {
|
||||
@@ -78,6 +86,12 @@ abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
|
||||
return execution.execute();
|
||||
}
|
||||
|
||||
protected <T> Iterable<T> execute(AbstractFunctionExecution execution, boolean returnResult) {
|
||||
execution.setTimeout(timeout)
|
||||
.setResultCollector(resultCollector);
|
||||
return execution.execute(returnResult);
|
||||
}
|
||||
|
||||
protected <T> T executeAndExtract(AbstractFunctionExecution execution) {
|
||||
execution.setTimeout(timeout)
|
||||
.setResultCollector(resultCollector);
|
||||
|
||||
@@ -49,6 +49,13 @@ public interface GemfireFunctionOperations {
|
||||
*/
|
||||
public abstract <T> Iterable<T> execute(String functionId, Object... args);
|
||||
|
||||
/**
|
||||
* Execute a function registered with an ID with no return value
|
||||
* @param functionId the function ID
|
||||
* @param args the calling arguments
|
||||
*/
|
||||
public void executeWithNoResult(String functionId, Object... args);
|
||||
|
||||
/**
|
||||
* Execute a function registered with an ID and with an expected singleton result
|
||||
* @param functionId the function ID
|
||||
|
||||
@@ -50,5 +50,4 @@ public class GemfireOnMemberFunctionTemplate extends AbstractFunctionTemplate {
|
||||
}
|
||||
return new DistributedMemberFunctionExecution(this.distributedMember);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,51 +23,46 @@ import com.gemstone.gemfire.cache.execute.Function;
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations {
|
||||
|
||||
public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations {
|
||||
|
||||
private Region<?, ?> region;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param region
|
||||
*/
|
||||
public GemfireOnRegionFunctionTemplate(Region<?,?> region) {
|
||||
Assert.notNull(region, "Region cannot be null");
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
|
||||
return execute(new RegionFunctionExecution(region)
|
||||
.setKeys(keys)
|
||||
.setFunction(function)
|
||||
.setTimeout(timeout)
|
||||
.setArgs(args) );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
|
||||
return execute(new RegionFunctionExecution(region)
|
||||
.setKeys(keys)
|
||||
.setFunctionId(functionId)
|
||||
.setTimeout(timeout)
|
||||
.setArgs(args) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
|
||||
return this.<T> executeAndExtract(new RegionFunctionExecution(region)
|
||||
.setKeys(keys)
|
||||
.setFunctionId(functionId)
|
||||
.setTimeout(timeout)
|
||||
.setArgs(args) );
|
||||
public GemfireOnRegionFunctionTemplate(Region<?, ?> region) {
|
||||
Assert.notNull(region, "Region cannot be null");
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFunctionExecution getFunctionExecution() {
|
||||
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
|
||||
return execute(new RegionFunctionExecution(region).setKeys(keys).setFunction(function).setTimeout(timeout)
|
||||
.setArgs(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
|
||||
return execute(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId).setTimeout(timeout)
|
||||
.setArgs(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
|
||||
return this.<T> executeAndExtract(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId)
|
||||
.setTimeout(timeout).setArgs(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFunctionExecution getFunctionExecution() {
|
||||
return new RegionFunctionExecution(this.region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeWithNoResult(String functionId, Set<?> keys, Object... args) {
|
||||
execute(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId).setTimeout(timeout)
|
||||
.setArgs(args), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ public interface GemfireOnRegionOperations extends GemfireFunctionOperations {
|
||||
|
||||
public abstract <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args);
|
||||
public abstract <T> Iterable<T> execute(Function function, Set<?> keys, Object... args);
|
||||
public abstract void executeWithNoResult(String functionId, Set<?> keys, Object... args);
|
||||
public abstract <T> T executeAndextract(String functionId, Set<?> keys, Object... args);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user