SGF-358 - Enhance SDG's Function annotation support to allow strongly-typed arguments in the context of PDX even when read-serialized is set to true.
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.function;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.gemstone.gemfire.cache.execute.FunctionContext;
|
||||
|
||||
/**
|
||||
@@ -23,7 +25,19 @@ class DefaultFunctionArgumentResolver implements FunctionArgumentResolver {
|
||||
|
||||
private static final Object[] EMPTY_ARRAY = new Object[0];
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.reflect.Method
|
||||
*/
|
||||
@Override
|
||||
public Method getFunctionAnnotatedMethod() {
|
||||
throw new UnsupportedOperationException("Not Implemented!");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.gemfire.function.FunctionArgumentResolver#resolveFunctionArguments(com.gemstone.gemfire.cache.execute.FunctionContext)
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -12,14 +12,23 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.function;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.gemstone.gemfire.cache.execute.FunctionContext;
|
||||
|
||||
/**
|
||||
* Strategy Interface for resolving function invocation arguments, given a {@link FunctionContext}
|
||||
* @author David Turanski
|
||||
* @since 1.3.0
|
||||
* The FunctionArgumentResolver interface is a Strategy Interface for resolving Function invocation arguments,
|
||||
* given a {@link FunctionContext}.
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see com.gemstone.gemfire.cache.execute.FunctionContext
|
||||
* @since 1.3.0
|
||||
*/
|
||||
interface FunctionArgumentResolver {
|
||||
|
||||
Method getFunctionAnnotatedMethod();
|
||||
|
||||
Object[] resolveFunctionArguments(FunctionContext functionContext);
|
||||
|
||||
}
|
||||
|
||||
@@ -34,68 +34,68 @@ import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
|
||||
* @since 1.3.0
|
||||
*
|
||||
*/
|
||||
class FunctionContextInjectingArgumentResolver extends DefaultFunctionArgumentResolver {
|
||||
class FunctionContextInjectingArgumentResolver extends PdxFunctionArgumentResolver {
|
||||
|
||||
private static Log logger = LogFactory.getLog(FunctionContextInjectingArgumentResolver.class);
|
||||
private static final Log logger = LogFactory.getLog(FunctionContextInjectingArgumentResolver.class);
|
||||
|
||||
private final int regionParameterPosition;
|
||||
private final int filterParameterPosition;
|
||||
private final int functionContextParameterPosition;
|
||||
private final int regionParameterPosition;
|
||||
private final int resultSenderParameterPosition;
|
||||
|
||||
private final Method method;
|
||||
|
||||
public FunctionContextInjectingArgumentResolver(Method method) {
|
||||
|
||||
this.method = method;
|
||||
int annotatedRegionDataParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method,
|
||||
RegionData.class, new Class[] { Map.class });
|
||||
|
||||
int regionDataAnnotationParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition(
|
||||
method, RegionData.class, new Class[] { Map.class });
|
||||
|
||||
int regionTypeParameterPosition = getArgumentTypePosition(method, Region.class);
|
||||
|
||||
if (annotatedRegionDataParameterPosition >= 0 && regionTypeParameterPosition >= 0) {
|
||||
Assert.isTrue(
|
||||
annotatedRegionDataParameterPosition == regionTypeParameterPosition,
|
||||
String.format(
|
||||
"Function method signature for method %s cannot contain an @RegionData parameter and a different Region type parameter",
|
||||
method.getName()));
|
||||
if (regionDataAnnotationParameterPosition >= 0 && regionTypeParameterPosition >= 0) {
|
||||
Assert.isTrue(regionDataAnnotationParameterPosition == regionTypeParameterPosition, String.format(
|
||||
"Function method signature for method %s cannot contain an @RegionData parameter and a different Region type parameter",
|
||||
method.getName()));
|
||||
}
|
||||
|
||||
int tempRegionParameterPosition = -1;
|
||||
regionParameterPosition = (regionDataAnnotationParameterPosition >= 0 ? regionDataAnnotationParameterPosition
|
||||
: (regionTypeParameterPosition >= 0 ? regionTypeParameterPosition : -1));
|
||||
|
||||
if (annotatedRegionDataParameterPosition >= 0) {
|
||||
tempRegionParameterPosition = annotatedRegionDataParameterPosition;
|
||||
} else if (regionTypeParameterPosition >= 0) {
|
||||
tempRegionParameterPosition = regionTypeParameterPosition;
|
||||
}
|
||||
|
||||
regionParameterPosition = tempRegionParameterPosition;
|
||||
filterParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method, Filter.class,
|
||||
new Class[] { Set.class });
|
||||
functionContextParameterPosition = getArgumentTypePosition(method, FunctionContext.class);
|
||||
resultSenderParameterPosition = getArgumentTypePosition(method, ResultSender.class);
|
||||
new Class[] { Set.class });
|
||||
|
||||
if (regionParameterPosition >= 0 && filterParameterPosition >= 0) {
|
||||
Assert.state(regionParameterPosition != filterParameterPosition,
|
||||
"region parameter and filter parameter must be different");
|
||||
"region parameter and filter parameter must be different");
|
||||
}
|
||||
|
||||
functionContextParameterPosition = getArgumentTypePosition(method, FunctionContext.class);
|
||||
|
||||
resultSenderParameterPosition = getArgumentTypePosition(method, ResultSender.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method getFunctionAnnotatedMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] resolveFunctionArguments(FunctionContext functionContext) {
|
||||
|
||||
Object[] args = super.resolveFunctionArguments(functionContext);
|
||||
|
||||
if (functionContext instanceof RegionFunctionContext) {
|
||||
if (this.regionParameterPosition >= 0) {
|
||||
args = ArrayUtils.insert(args, regionParameterPosition,
|
||||
getRegionForContext((RegionFunctionContext) functionContext));
|
||||
args = ArrayUtils.insert(args, regionParameterPosition, getRegionForContext(
|
||||
(RegionFunctionContext) functionContext));
|
||||
}
|
||||
|
||||
if (this.filterParameterPosition >= 0) {
|
||||
args = ArrayUtils.insert(args, filterParameterPosition,
|
||||
((RegionFunctionContext) functionContext).getFilter());
|
||||
((RegionFunctionContext) functionContext).getFilter());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.functionContextParameterPosition >= 0) {
|
||||
args = ArrayUtils.insert(args, functionContextParameterPosition, functionContext);
|
||||
}
|
||||
@@ -105,47 +105,53 @@ class FunctionContextInjectingArgumentResolver extends DefaultFunctionArgumentRe
|
||||
}
|
||||
|
||||
Assert.isTrue(args.length == method.getParameterTypes().length, String.format(
|
||||
"wrong number of arguments for method %s. Expected :%d, actual: %d", method.getName(),
|
||||
"wrong number of arguments for method %s. Expected %d, but was %d", method.getName(),
|
||||
method.getParameterTypes().length, args.length));
|
||||
|
||||
return args;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @param regionFunctionContext
|
||||
* @return
|
||||
* (non-Javadoc)
|
||||
* @see com.gemstone.gemfire.cache.execute.RegionFunctionContext
|
||||
*/
|
||||
private static Region<?, ?> getRegionForContext(RegionFunctionContext regionFunctionContext) {
|
||||
|
||||
Region<?, ?> region = regionFunctionContext.getDataSet();
|
||||
|
||||
if (PartitionRegionHelper.isPartitionedRegion(region)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("this is a partitioned region - filtering local data for context");
|
||||
}
|
||||
region = PartitionRegionHelper.getLocalDataForContext(regionFunctionContext);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("region contains " + region.size() + " items");
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
private static int getArgumentTypePosition(Method method, Class<?> requiredType) {
|
||||
int index = 0;
|
||||
int position = -1;
|
||||
int i = 0;
|
||||
for (Class<?> clazz : method.getParameterTypes()) {
|
||||
if (requiredType.equals(clazz)) {
|
||||
Assert.state(
|
||||
position < 0,
|
||||
String.format("Method %s signature cannot contain more than one parameter of type %s.",
|
||||
method.getName(), requiredType.getName()));
|
||||
position = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return position;
|
||||
|
||||
for (Class<?> parameterType : method.getParameterTypes()) {
|
||||
if (requiredType.equals(parameterType)) {
|
||||
Assert.state(position < 0, String.format(
|
||||
"Method %s signature cannot contain more than one parameter of type %s.",
|
||||
method.getName(), requiredType.getName()));
|
||||
|
||||
position = index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* 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.function;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
@@ -26,23 +27,23 @@ import org.springframework.util.StringUtils;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
public abstract class GemfireFunctionUtils {
|
||||
|
||||
private static Log log = LogFactory.getLog(GemfireFunctionUtils.class);
|
||||
|
||||
/**
|
||||
* Wrap a target object and method in a GemFire Function and register the function to the {@link FunctionService}
|
||||
*
|
||||
* Wrap a target object and method in a GemFire Function and register the function to the {@link FunctionService}
|
||||
*
|
||||
* @param target the target object
|
||||
* @param method the method bound to the function
|
||||
* @param attributes function attributes
|
||||
* @param overwrite if true, will replace the existing function
|
||||
*/
|
||||
public static void registerFunctionForPojoMethod(Object target, Method method, Map<String, Object> attributes,
|
||||
boolean overwrite) {
|
||||
boolean overwrite) {
|
||||
|
||||
String id = attributes.containsKey("id") ? (String) attributes.get("id") : "";
|
||||
|
||||
PojoFunctionWrapper function = new PojoFunctionWrapper(target, method, id);
|
||||
@@ -57,18 +58,15 @@ public abstract class GemfireFunctionUtils {
|
||||
|
||||
if (attributes.containsKey("batchSize")) {
|
||||
int batchSize = (Integer) attributes.get("batchSize");
|
||||
Assert.isTrue(
|
||||
batchSize >= 0,
|
||||
String.format("batchSize must be a non-negative value %s.%s", target.getClass().getName(),
|
||||
method.getName()));
|
||||
Assert.isTrue(batchSize >= 0, String.format("batchSize must be a non-negative value %1$s.%2$s",
|
||||
target.getClass().getName(), method.getName()));
|
||||
function.setBatchSize(batchSize);
|
||||
}
|
||||
|
||||
if (attributes.containsKey("hasResult")) {
|
||||
boolean hasResult = (Boolean) attributes.get("hasResult");
|
||||
//Only set if true
|
||||
if (hasResult) {
|
||||
function.setHasResult(hasResult);
|
||||
// only set if true TODO figure out why???
|
||||
if (Boolean.TRUE.equals(attributes.get("hasResult"))) {
|
||||
function.setHasResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +84,8 @@ public abstract class GemfireFunctionUtils {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("registered function " + function.getId());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("function " + function.getId() + "is already registered");
|
||||
}
|
||||
@@ -95,7 +94,7 @@ public abstract class GemfireFunctionUtils {
|
||||
|
||||
/**
|
||||
* Determine the order position of a an annotated method parameter
|
||||
*
|
||||
*
|
||||
* @param method the {@link Method} instance
|
||||
* @param targetAnnotationType the annotation
|
||||
* @param requiredTypes an array of valid parameter types for the annotation
|
||||
@@ -103,42 +102,48 @@ public abstract class GemfireFunctionUtils {
|
||||
*/
|
||||
public static int getAnnotationParameterPosition(Method method, Class<?> targetAnnotationType,
|
||||
Class<?>[] requiredTypes) {
|
||||
|
||||
int position = -1;
|
||||
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
|
||||
if (parameterAnnotations.length > 0) {
|
||||
int position = -1;
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
|
||||
List<Class<?>> requiredTypesList = Arrays.asList(requiredTypes);
|
||||
|
||||
for (int i = 0; i < parameterAnnotations.length; i++) {
|
||||
Annotation[] annotations = parameterAnnotations[i];
|
||||
for (int index = 0; index < parameterAnnotations.length; index++) {
|
||||
Annotation[] annotations = parameterAnnotations[index];
|
||||
|
||||
if (annotations.length > 0) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType().equals(targetAnnotationType)) {
|
||||
Assert.state(
|
||||
position < 0,
|
||||
String.format(
|
||||
"Method %s signature cannot contain more than one parameter annotated with type %s",
|
||||
method.getName(), targetAnnotationType.getName()));
|
||||
Assert.state(position < 0, String.format(
|
||||
"Method %s signature cannot contain more than one parameter annotated with type %s",
|
||||
method.getName(), targetAnnotationType.getName()));
|
||||
|
||||
boolean isRequiredType = false;
|
||||
for (Class<?> requiredType: requiredTypesList) {
|
||||
if (requiredType.isAssignableFrom(paramTypes[i])) {
|
||||
|
||||
for (Class<?> requiredType : requiredTypesList) {
|
||||
if (requiredType.isAssignableFrom(parameterTypes[index])) {
|
||||
isRequiredType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.isTrue(isRequiredType, String.format(
|
||||
"Parameter of type %s annotated with %s must be assignable from one of type %s in method %s",
|
||||
paramTypes[i], targetAnnotationType.getName(),
|
||||
StringUtils.arrayToCommaDelimitedString(requiredTypes), method.getName()));
|
||||
position = i;
|
||||
}
|
||||
|
||||
Assert.isTrue(isRequiredType, String.format(
|
||||
"Parameter of type %s annotated with %s must be assignable from one of type %s in method %s",
|
||||
parameterTypes[index], targetAnnotationType.getName(),
|
||||
StringUtils.arrayToCommaDelimitedString(requiredTypes), method.getName()));
|
||||
|
||||
position = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
return -1;
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.CacheClosedException;
|
||||
import com.gemstone.gemfire.cache.CacheFactory;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionContext;
|
||||
import com.gemstone.gemfire.pdx.PdxInstance;
|
||||
|
||||
/**
|
||||
* The PdxFunctionArgumentResolver class is a Spring Data GemFire FunctionArgumentResolver that automatically resolves
|
||||
* PDX types when GemFire is configured with read-serialized set to true, but the application domain classes
|
||||
* are actually on the classpath.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.function.DefaultFunctionArgumentResolver
|
||||
* @see com.gemstone.gemfire.pdx.PdxInstance
|
||||
* @since 1.5.2
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
class PdxFunctionArgumentResolver extends DefaultFunctionArgumentResolver {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.gemstone.gemfire.cache.execute.FunctionContext
|
||||
*/
|
||||
@Override
|
||||
public Object[] resolveFunctionArguments(final FunctionContext functionContext) {
|
||||
Object[] functionArguments = super.resolveFunctionArguments(functionContext);
|
||||
|
||||
if (isPdxSerializerConfigured()) {
|
||||
int index = 0;
|
||||
|
||||
for (Object functionArgument : functionArguments) {
|
||||
if (functionArgument instanceof PdxInstance) {
|
||||
String className = ((PdxInstance) functionArgument).getClassName();
|
||||
|
||||
if (isDeserializationNecessary(className)) {
|
||||
functionArguments[index] = ((PdxInstance) functionArgument).getObject();
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return functionArguments;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.reflect.Method
|
||||
*/
|
||||
@Override
|
||||
public Method getFunctionAnnotatedMethod() {
|
||||
throw new UnsupportedOperationException("Not Implemented!");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.gemstone.gemfire.cache.Cache#getPdxSerializer()
|
||||
* @see com.gemstone.gemfire.cache.CacheFactory#getAnyInstance()
|
||||
*/
|
||||
boolean isPdxSerializerConfigured() {
|
||||
try {
|
||||
return (CacheFactory.getAnyInstance().getPdxSerializer() != null);
|
||||
}
|
||||
catch (CacheClosedException ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadac)
|
||||
*
|
||||
* @see #isOnClasspath(String)
|
||||
* @see #functionAnnotatedMethodHasParameterOfType(String)
|
||||
*/
|
||||
boolean isDeserializationNecessary(final String className) {
|
||||
return (isOnClasspath(className) && functionAnnotatedMethodHasParameterOfType(className));
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Thread#currentThread()
|
||||
* @see java.lang.Thread#getContextClassLoader()
|
||||
* @see org.springframework.util.ClassUtils#isPresent(String, ClassLoader)
|
||||
*/
|
||||
boolean isOnClasspath(final String className) {
|
||||
return ClassUtils.isPresent(className, Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see #getFunctionAnnotatedMethod()
|
||||
* @see java.lang.reflect.Method#getParameterTypes()
|
||||
*/
|
||||
boolean functionAnnotatedMethodHasParameterOfType(final String className) {
|
||||
for (Class<?> parameterType : getFunctionAnnotatedMethod().getParameterTypes()) {
|
||||
if (parameterType.getName().equals(className)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,74 +41,70 @@ public class PojoFunctionWrapper implements Function {
|
||||
private static transient Log logger = LogFactory.getLog(PojoFunctionWrapper.class);
|
||||
|
||||
private volatile boolean HA;
|
||||
private volatile boolean optimizeForWrite;
|
||||
private volatile boolean hasResult;
|
||||
private final Object target;
|
||||
private final Method method;
|
||||
private final String id;
|
||||
private volatile boolean optimizeForWrite;
|
||||
|
||||
private volatile int batchSize;
|
||||
|
||||
private final FunctionArgumentResolver functionArgumentResolver;
|
||||
|
||||
private final Method method;
|
||||
|
||||
private final Object target;
|
||||
|
||||
private final String id;
|
||||
|
||||
public PojoFunctionWrapper(Object target, Method method, String id) {
|
||||
|
||||
this.functionArgumentResolver = new FunctionContextInjectingArgumentResolver(method);
|
||||
|
||||
this.id = StringUtils.hasText(id) ? id : method.getName();
|
||||
this.target = target;
|
||||
this.method = method;
|
||||
|
||||
this.id = (StringUtils.hasText(id) ? id : method.getName());
|
||||
this.HA = false;
|
||||
|
||||
this.hasResult = !(method.getReturnType().equals(void.class));
|
||||
|
||||
this.optimizeForWrite = false;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public boolean hasResult() {
|
||||
return this.hasResult;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public boolean isHA() {
|
||||
return this.HA;
|
||||
}
|
||||
|
||||
public void setHA(boolean HA) {
|
||||
this.HA = HA;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public boolean optimizeForWrite() {
|
||||
return this.optimizeForWrite;
|
||||
}
|
||||
|
||||
public void setOptimizeForWrite(boolean optimizeForWrite) {
|
||||
this.optimizeForWrite = optimizeForWrite;
|
||||
}
|
||||
|
||||
public void setBatchSize(int batchSize) {
|
||||
this.batchSize = batchSize;
|
||||
}
|
||||
|
||||
public void setHA(boolean HA) {
|
||||
this.HA = HA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHA() {
|
||||
return this.HA;
|
||||
}
|
||||
|
||||
public void setHasResult(boolean hasResult) {
|
||||
this.hasResult = hasResult;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void execute(FunctionContext functionContext) {
|
||||
@Override
|
||||
public boolean hasResult() {
|
||||
return this.hasResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setOptimizeForWrite(boolean optimizeForWrite) {
|
||||
this.optimizeForWrite = optimizeForWrite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean optimizeForWrite() {
|
||||
return this.optimizeForWrite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final FunctionContext functionContext) {
|
||||
Object[] args = this.functionArgumentResolver.resolveFunctionArguments(functionContext);
|
||||
|
||||
Object result = null;
|
||||
|
||||
result = invokeTargetMethod(args);
|
||||
Object result = invokeTargetMethod(args);
|
||||
|
||||
if (hasResult()) {
|
||||
sendResults(functionContext.getResultSender(), result);
|
||||
@@ -116,32 +112,33 @@ public class PojoFunctionWrapper implements Function {
|
||||
}
|
||||
|
||||
protected final Object invokeTargetMethod(Object[] args) {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("about to invoke method %s on class %s as function %s", method.getName(), target
|
||||
.getClass().getName(), this.id));
|
||||
logger.debug(String.format("about to invoke method %s on class %s as function %s", method.getName(),
|
||||
target.getClass().getName(), this.id));
|
||||
|
||||
for (Object arg : args) {
|
||||
logger.debug("arg:" + arg.getClass().getName() + " " + arg.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (Object) ReflectionUtils.invokeMethod(method, target, (Object[]) args);
|
||||
return ReflectionUtils.invokeMethod(method, target, (Object[]) args);
|
||||
}
|
||||
|
||||
private void sendResults(ResultSender<Object> resultSender, Object result) {
|
||||
if (result == null) {
|
||||
resultSender.lastResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ObjectUtils.isArray(result)) {
|
||||
new BatchingResultSender(batchSize, resultSender).sendArrayResults(result);
|
||||
} else if (Iterable.class.isAssignableFrom(result.getClass())) {
|
||||
new BatchingResultSender(batchSize, resultSender).sendResults((Iterable<?>) result);
|
||||
} else {
|
||||
resultSender.lastResult(result);
|
||||
else {
|
||||
if (ObjectUtils.isArray(result)) {
|
||||
new BatchingResultSender(batchSize, resultSender).sendArrayResults(result);
|
||||
}
|
||||
else if (Iterable.class.isAssignableFrom(result.getClass())) {
|
||||
new BatchingResultSender(batchSize, resultSender).sendResults((Iterable<?>) result);
|
||||
}
|
||||
else {
|
||||
resultSender.lastResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user