From bfe0a6c93d6fef0149a23a432a0504bb71f21007 Mon Sep 17 00:00:00 2001 From: Patrick Johnson Date: Mon, 10 Feb 2020 13:07:03 -0800 Subject: [PATCH] Enable Function Executions to return results from all servers. Refer to DATAGEODE-295. Resolves gh-37. --- .../execution/AbstractFunctionExecution.java | 3 + .../GemfireFunctionProxyFactoryBean.java | 55 +++++++++++++------ .../onservers/AllServersAdminFunctions.java | 7 ++- ...ResultsFromAllServersIntegrationTests.java | 4 +- .../function/execution/onservers/Metric.java | 2 +- .../onservers/SingleServerAdminFunctions.java | 3 +- 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionExecution.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionExecution.java index 1558eab7..18267396 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionExecution.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionExecution.java @@ -40,11 +40,14 @@ import org.slf4j.LoggerFactory; * @author David Turanski * @author John Blum * @author Patrick Johnson +<<<<<<< HEAD * @see java.util.concurrent.TimeUnit * @see org.apache.geode.cache.execute.Execution * @see org.apache.geode.cache.execute.Function * @see org.apache.geode.cache.execute.FunctionService * @see org.apache.geode.cache.execute.ResultCollector +======= +>>>>>>> ae69760bf... DATAGEODE-295 - Functions return results from all servers. */ @SuppressWarnings("unused") abstract class AbstractFunctionExecution { diff --git a/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java b/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java index 7634cc6b..270b4395 100644 --- a/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java +++ b/spring-data-geode/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java @@ -13,12 +13,16 @@ package org.springframework.data.gemfire.function.execution; import java.lang.reflect.Method; +import java.util.function.Function; import java.util.stream.StreamSupport; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.FactoryBean; +import org.springframework.data.gemfire.function.annotation.OnServers; import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -43,24 +47,25 @@ public class GemfireFunctionProxyFactoryBean extends AbstractFactoryBeanSupport< private final Class functionExecutionInterface; - private FunctionExecutionMethodMetadata methodMetadata; + private final FunctionExecutionMethodMetadata methodMetadata; private final GemfireFunctionOperations gemfireFunctionOperations; private volatile Object functionExecutionProxy; /** - * Constructs a new instance of the {@link GemfireFunctionProxyFactoryBean} initialized with the given + * Constructs a new instance of {@link GemfireFunctionProxyFactoryBean} initialized with the given * {@link Class Function Excution Interface} and {@link GemfireFunctionOperations}. * - * @param functionExecutionInterface {@link Class Function Execution Interface} to proxy. - * @param gemfireFunctionOperations Template class used to delegate the Function invocation. - * @see org.springframework.data.gemfire.function.execution.GemfireFunctionOperations + * @param functionExecutionInterface {@link Class Function Execution Interface} to proxy; + * must not be {@literal null}. + * @param gemfireFunctionOperations template used to execute the {@link Function}. * @throws IllegalArgumentException if the {@link Class Function Execution Interface} is {@literal null} * or the {@link Class Function Execution Type} is not an actual interface. + * @see org.springframework.data.gemfire.function.execution.GemfireFunctionOperations */ - public GemfireFunctionProxyFactoryBean(Class functionExecutionInterface, - GemfireFunctionOperations gemfireFunctionOperations) { + public GemfireFunctionProxyFactoryBean(@NonNull Class functionExecutionInterface, + @NonNull GemfireFunctionOperations gemfireFunctionOperations) { Assert.notNull(functionExecutionInterface, "Function Execution Interface must not be null"); @@ -73,8 +78,11 @@ public class GemfireFunctionProxyFactoryBean extends AbstractFactoryBeanSupport< this.methodMetadata = new DefaultFunctionExecutionMethodMetadata(functionExecutionInterface); } + /** + * @inheritDoc + */ @Override - public ClassLoader getBeanClassLoader() { + public @NonNull ClassLoader getBeanClassLoader() { ClassLoader beanClassLoader = super.getBeanClassLoader(); @@ -85,16 +93,19 @@ public class GemfireFunctionProxyFactoryBean extends AbstractFactoryBeanSupport< return this.functionExecutionInterface; } - protected FunctionExecutionMethodMetadata getFunctionExecutionMethodMetadata() { + protected @NonNull FunctionExecutionMethodMetadata getFunctionExecutionMethodMetadata() { return this.methodMetadata; } - protected GemfireFunctionOperations getGemfireFunctionOperations() { + protected @NonNull GemfireFunctionOperations getGemfireFunctionOperations() { return this.gemfireFunctionOperations; } + /** + * @inheritDoc + */ @Override - public Object invoke(MethodInvocation invocation) { + public @Nullable Object invoke(@NonNull MethodInvocation invocation) { if (AopUtils.isToStringMethod(invocation.getMethod())) { return String.format("Function Proxy for interface [%s]", getFunctionExecutionInterface().getName()); @@ -107,13 +118,19 @@ public class GemfireFunctionProxyFactoryBean extends AbstractFactoryBeanSupport< return resolveResult(invocation, result); } - protected Object invokeFunction(Method method, Object[] args) { + protected @Nullable Object invokeFunction(@NonNull Method method, @NonNull Object[] args) { - String functionId = getFunctionExecutionMethodMetadata() - .getMethodMetadata(method) - .getFunctionId(); + GemfireFunctionOperations template = getGemfireFunctionOperations(); - return getGemfireFunctionOperations().execute(functionId, args); + String functionId = getFunctionExecutionMethodMetadata().getMethodMetadata(method).getFunctionId(); + + return isFunctionExecutionForAllServers(method) + ? template.execute(functionId, args) + : template.executeAndExtract(functionId, args); + } + + private boolean isFunctionExecutionForAllServers(Method method) { + return method.getDeclaringClass().isAnnotationPresent(OnServers.class); } protected Object resolveResult(MethodInvocation invocation, Object result) { @@ -147,6 +164,9 @@ public class GemfireFunctionProxyFactoryBean extends AbstractFactoryBeanSupport< return value instanceof Iterable; } + /** + * @inheritDoc + */ @Override public Object getObject() throws Exception { @@ -158,6 +178,9 @@ public class GemfireFunctionProxyFactoryBean extends AbstractFactoryBeanSupport< return this.functionExecutionProxy; } + /** + * @inheritDoc + */ @Override public Class getObjectType() { return getFunctionExecutionInterface(); diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/AllServersAdminFunctions.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/AllServersAdminFunctions.java index b3b16ab1..d4bcd526 100644 --- a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/AllServersAdminFunctions.java +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/AllServersAdminFunctions.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2021 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. @@ -16,11 +16,11 @@ */ package org.springframework.data.gemfire.function.execution.onservers; +import java.util.List; + import org.springframework.data.gemfire.function.annotation.FunctionId; import org.springframework.data.gemfire.function.annotation.OnServers; -import java.util.List; - /** * @author Patrick Johnson */ @@ -29,4 +29,5 @@ public interface AllServersAdminFunctions { @FunctionId("GetAllMetricsFunction") List> getAllMetrics(); + } diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/FunctionsReturnResultsFromAllServersIntegrationTests.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/FunctionsReturnResultsFromAllServersIntegrationTests.java index 519c34c0..2b2ec4b0 100644 --- a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/FunctionsReturnResultsFromAllServersIntegrationTests.java +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/FunctionsReturnResultsFromAllServersIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2021 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. @@ -113,6 +113,7 @@ public class FunctionsReturnResultsFromAllServersIntegrationTests extends Client private static final int DEFAULT_CACHE_SERVER_PORT = 40404; private static final String CACHE_SERVER_PORT_PROPERTY = "spring.data.gemfire.cache.server.port"; + private static final String GEMFIRE_LOG_LEVEL = "error"; private static final String GEMFIRE_NAME = "MetricsServer" + getCacheServerPort(); public static void main(String[] args) throws Exception { @@ -123,6 +124,7 @@ public class FunctionsReturnResultsFromAllServersIntegrationTests extends Client return new CacheFactory() .set("name", GEMFIRE_NAME) + .set("log-level", GEMFIRE_LOG_LEVEL) .create(); } diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/Metric.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/Metric.java index fe1f550d..74d9f7c4 100644 --- a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/Metric.java +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/Metric.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2021 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. diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/SingleServerAdminFunctions.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/SingleServerAdminFunctions.java index 89d1838e..6a658f15 100644 --- a/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/SingleServerAdminFunctions.java +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/function/execution/onservers/SingleServerAdminFunctions.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2021 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. @@ -29,4 +29,5 @@ public interface SingleServerAdminFunctions { @FunctionId("GetAllMetricsFunction") List getAllMetrics(); + }