From 89cafeba2d1fbb141eec5886dcb7f541f0370b62 Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 12 Jun 2018 19:42:55 -0700 Subject: [PATCH] DATAGEODE-122 - Refactor Function annotation configuration to be smarter in resolving Apache Geode objects on startup. Renames OnMember, OnMembers, OnRegion, OnServer and OnServers *ExecutionBeanDefinitionBuilder classes to *FunctionExecutionBeanDefinitionBuilder. --- .../remote/FunctionGemfireAdminTemplate.java | 5 - .../DefaultFunctionArgumentResolver.java | 18 +- ...ctionContextInjectingArgumentResolver.java | 14 +- .../function/PdxFunctionArgumentResolver.java | 11 +- .../gemfire/function/PojoFunctionWrapper.java | 17 +- ...unctionExecutionBeanDefinitionBuilder.java | 36 ++-- ...ExecutionBeanDefinitionBuilderFactory.java | 31 ++-- ...ctionExecutionBeanDefinitionRegistrar.java | 14 +- .../FunctionExecutionConfiguration.java | 51 +++--- ...nctionExecutionBeanDefinitionBuilder.java} | 25 ++- ...nctionExecutionBeanDefinitionBuilder.java} | 23 ++- ...nctionExecutionBeanDefinitionBuilder.java} | 23 ++- ...nctionExecutionBeanDefinitionBuilder.java} | 39 ++-- ...nctionExecutionBeanDefinitionBuilder.java} | 11 +- ...nctionExecutionBeanDefinitionBuilder.java} | 16 +- ...nctionExecutionBeanDefinitionBuilder.java} | 40 +++-- .../execution/AbstractFunctionTemplate.java | 15 +- .../GemfireFunctionProxyFactoryBean.java | 34 ++-- .../GemfireOnRegionFunctionTemplate.java | 65 ++++--- .../execution/GemfireOnRegionOperations.java | 30 +++- .../GemfireOnServerFunctionTemplate.java | 89 +++++++++- .../GemfireOnServersFunctionTemplate.java | 97 ++++++++-- .../GroupMemberFunctionExecution.java | 29 ++- .../GroupMembersFunctionExecution.java | 28 ++- .../PoolServerFunctionExecution.java | 45 ++--- .../PoolServersFunctionExecution.java | 27 +-- .../execution/ServerFunctionExecution.java | 23 ++- .../execution/ServersFunctionExecution.java | 30 ++-- .../data/gemfire/util/SpringUtils.java | 8 + ...FunctionGemfireAdminTemplateUnitTests.java | 5 +- ...ecutionBeanDefinitionBuilderUnitTests.java | 98 ++++++++++ ...cutionBeanDefinitionBuilderUnitTests.java} | 133 ++++++++------ ...ireFunctionProxyFactoryBeanUnitTests.java} | 167 +++++++++--------- 33 files changed, 833 insertions(+), 464 deletions(-) rename src/main/java/org/springframework/data/gemfire/function/config/{MemberBasedExecutionBeanDefinitionBuilder.java => MemberBasedFunctionExecutionBeanDefinitionBuilder.java} (79%) rename src/main/java/org/springframework/data/gemfire/function/config/{OnMemberExecutionBeanDefinitionBuilder.java => OnMemberFunctionExecutionBeanDefinitionBuilder.java} (73%) rename src/main/java/org/springframework/data/gemfire/function/config/{OnMembersExecutionBeanDefinitionBuilder.java => OnMembersFunctionExecutionBeanDefinitionBuilder.java} (73%) rename src/main/java/org/springframework/data/gemfire/function/config/{OnRegionExecutionBeanDefinitionBuilder.java => OnRegionFunctionExecutionBeanDefinitionBuilder.java} (64%) rename src/main/java/org/springframework/data/gemfire/function/config/{OnServerExecutionBeanDefinitionBuilder.java => OnServerFunctionExecutionBeanDefinitionBuilder.java} (79%) rename src/main/java/org/springframework/data/gemfire/function/config/{OnServersExecutionBeanDefinitionBuilder.java => OnServersFunctionExecutionBeanDefinitionBuilder.java} (74%) rename src/main/java/org/springframework/data/gemfire/function/config/{ServerBasedExecutionBeanDefinitionBuilder.java => ServerBasedFunctionExecutionBeanDefinitionBuilder.java} (66%) create mode 100644 src/test/java/org/springframework/data/gemfire/function/config/MemberBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java rename src/test/java/org/springframework/data/gemfire/function/config/{ServerBasedExecutionBeanDefinitionBuilderTest.java => ServerBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java} (52%) rename src/test/java/org/springframework/data/gemfire/function/execution/{GemfireFunctionProxyFactoryBeanTests.java => GemfireFunctionProxyFactoryBeanUnitTests.java} (51%) diff --git a/src/main/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplate.java b/src/main/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplate.java index 8bd525fd..f1c4862b 100644 --- a/src/main/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplate.java +++ b/src/main/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplate.java @@ -139,27 +139,22 @@ public class FunctionGemfireAdminTemplate extends AbstractGemfireAdminOperations execute(CreateIndexFunction.CREATE_INDEX_FUNCTION_ID, indexDefinition); } - /* (non-Javadoc) */ T execute(Function gemfireFunction, Object... arguments) { return newGemfireFunctionOperations().executeAndExtract(gemfireFunction, arguments); } - /* (non-Javadoc) */ T execute(String gemfireFunctionId, Object... arguments) { return newGemfireFunctionOperations().executeAndExtract(gemfireFunctionId, arguments); } - /* (non-Javadoc) */ protected GemfireFunctionOperations newGemfireFunctionOperations() { return newGemfireFunctionOperations(getClientCache()); } - /* (non-Javadoc) */ protected GemfireFunctionOperations newGemfireFunctionOperations(ClientCache clientCache) { return new GemfireOnServersFunctionTemplate(clientCache); } - /* (non-Javadoc) */ boolean containsRegionInformation(Object results) { return Optional.ofNullable(results) diff --git a/src/main/java/org/springframework/data/gemfire/function/DefaultFunctionArgumentResolver.java b/src/main/java/org/springframework/data/gemfire/function/DefaultFunctionArgumentResolver.java index 03a8bb19..33212a1f 100644 --- a/src/main/java/org/springframework/data/gemfire/function/DefaultFunctionArgumentResolver.java +++ b/src/main/java/org/springframework/data/gemfire/function/DefaultFunctionArgumentResolver.java @@ -27,7 +27,6 @@ class DefaultFunctionArgumentResolver implements FunctionArgumentResolver { /* * (non-Javadoc) - * * @see java.lang.reflect.Method */ @Override @@ -37,28 +36,33 @@ class DefaultFunctionArgumentResolver implements FunctionArgumentResolver { /* * (non-Javadoc) - * * @see org.springframework.data.gemfire.function.FunctionArgumentResolver#resolveFunctionArguments(org.apache.geode.cache.execute.FunctionContext) */ @Override public Object[] resolveFunctionArguments(final FunctionContext functionContext) { - return (isArray(functionContext.getArguments())) ? toObjectArray((Object[]) functionContext.getArguments()) + + return isArray(functionContext.getArguments()) + ? toObjectArray((Object[]) functionContext.getArguments()) : getArguments(functionContext); } private boolean isArray(final Object value) { - return (value != null && value.getClass().isArray()); + return value != null && value.getClass().isArray(); } private Object[] toObjectArray(final Object[] arguments) { + Object[] result = new Object[arguments.length]; + System.arraycopy(arguments, 0, result, 0, arguments.length); + return result; } private Object[] getArguments(final FunctionContext context) { - Object arguments = context.getArguments(); - return (arguments != null ? new Object[] { arguments } : EMPTY_ARRAY); - } + Object arguments = context.getArguments(); + + return arguments != null ? new Object[] { arguments } : EMPTY_ARRAY; + } } diff --git a/src/main/java/org/springframework/data/gemfire/function/FunctionContextInjectingArgumentResolver.java b/src/main/java/org/springframework/data/gemfire/function/FunctionContextInjectingArgumentResolver.java index b84bf1c9..ffab5803 100644 --- a/src/main/java/org/springframework/data/gemfire/function/FunctionContextInjectingArgumentResolver.java +++ b/src/main/java/org/springframework/data/gemfire/function/FunctionContextInjectingArgumentResolver.java @@ -45,6 +45,7 @@ class FunctionContextInjectingArgumentResolver extends PdxFunctionArgumentResolv private final Method method; public FunctionContextInjectingArgumentResolver(Method method) { + this.method = method; int regionDataAnnotationParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition( @@ -76,11 +77,12 @@ class FunctionContextInjectingArgumentResolver extends PdxFunctionArgumentResolv @Override public Method getFunctionAnnotatedMethod() { - return method; + return this.method; } @Override public Object[] resolveFunctionArguments(FunctionContext functionContext) { + Object[] args = super.resolveFunctionArguments(functionContext); if (functionContext instanceof RegionFunctionContext) { @@ -103,9 +105,9 @@ class FunctionContextInjectingArgumentResolver extends PdxFunctionArgumentResolv args = ArrayUtils.insert(args, resultSenderParameterPosition, functionContext.getResultSender()); } - Assert.isTrue(args.length == method.getParameterTypes().length, String.format( - "wrong number of arguments for method %s. Expected %d, but was %d", method.getName(), - method.getParameterTypes().length, args.length)); + Assert.isTrue(args.length == this.method.getParameterTypes().length, + String.format("Wrong number of arguments for method [%s]; Expected [%d], but was [%d]", + this.method.getName(), this.method.getParameterTypes().length, args.length)); return args; } @@ -131,9 +133,6 @@ class FunctionContextInjectingArgumentResolver extends PdxFunctionArgumentResolv return region; } - /* - * (non-Javadoc) - */ private static int getArgumentTypePosition(Method method, Class requiredType) { int index = 0; int position = -1; @@ -152,5 +151,4 @@ class FunctionContextInjectingArgumentResolver extends PdxFunctionArgumentResolv return position; } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/PdxFunctionArgumentResolver.java b/src/main/java/org/springframework/data/gemfire/function/PdxFunctionArgumentResolver.java index 12cbaa65..29f9f153 100644 --- a/src/main/java/org/springframework/data/gemfire/function/PdxFunctionArgumentResolver.java +++ b/src/main/java/org/springframework/data/gemfire/function/PdxFunctionArgumentResolver.java @@ -39,18 +39,20 @@ class PdxFunctionArgumentResolver extends DefaultFunctionArgumentResolver { /* * (non-Javadoc) - * * @see org.apache.geode.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)) { @@ -67,7 +69,6 @@ class PdxFunctionArgumentResolver extends DefaultFunctionArgumentResolver { /* * (non-Javadoc) - * * @see java.lang.reflect.Method */ @Override @@ -77,7 +78,6 @@ class PdxFunctionArgumentResolver extends DefaultFunctionArgumentResolver { /* * (non-Javadoc) - * * @see org.apache.geode.cache.Cache#getPdxSerializer() * @see org.apache.geode.cache.CacheFactory#getAnyInstance() */ @@ -92,16 +92,15 @@ class PdxFunctionArgumentResolver extends DefaultFunctionArgumentResolver { /* * (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) @@ -112,7 +111,6 @@ class PdxFunctionArgumentResolver extends DefaultFunctionArgumentResolver { /* * (non-Javadoc) - * * @see #getFunctionAnnotatedMethod() * @see java.lang.reflect.Method#getParameterTypes() */ @@ -125,5 +123,4 @@ class PdxFunctionArgumentResolver extends DefaultFunctionArgumentResolver { return false; } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/PojoFunctionWrapper.java b/src/main/java/org/springframework/data/gemfire/function/PojoFunctionWrapper.java index a527cd71..a8267cee 100644 --- a/src/main/java/org/springframework/data/gemfire/function/PojoFunctionWrapper.java +++ b/src/main/java/org/springframework/data/gemfire/function/PojoFunctionWrapper.java @@ -61,10 +61,11 @@ public class PojoFunctionWrapper implements Function { private final String id; public PojoFunctionWrapper(Object target, Method method, String id) { - this.functionArgumentResolver = new FunctionContextInjectingArgumentResolver(method); + this.target = target; this.method = method; - this.id = (StringUtils.hasText(id) ? id : method.getName()); + this.id = StringUtils.hasText(id) ? id : method.getName(); + this.functionArgumentResolver = new FunctionContextInjectingArgumentResolver(method); this.HA = false; this.hasResult = !method.getReturnType().equals(void.class); this.optimizeForWrite = false; @@ -108,7 +109,7 @@ public class PojoFunctionWrapper implements Function { @Override @SuppressWarnings("unchecked") - public void execute(final FunctionContext functionContext) { + public void execute(FunctionContext functionContext) { Object[] args = this.functionArgumentResolver.resolveFunctionArguments(functionContext); @@ -123,8 +124,10 @@ public class PojoFunctionWrapper implements Function { if (logger.isDebugEnabled()) { - logger.debug(String.format("About to invoke method [%s] on class [%s] as Function [%s]", - this.method.getName(), this.target.getClass().getName(), getId())); + if (logger.isDebugEnabled()) { + logger.debug(String.format("About to invoke method [%s] on class [%s] as Function [%s]", + this.method.getName(), this.target.getClass().getName(), getId())); + } for (Object arg : args) { logger.debug(String.format("Argument of type [%s] is [%s]", arg.getClass().getName(), arg.toString())); @@ -141,10 +144,10 @@ public class PojoFunctionWrapper implements Function { } else { if (ObjectUtils.isArray(result)) { - new BatchingResultSender(batchSize, resultSender).sendArrayResults(result); + new BatchingResultSender(this.batchSize, resultSender).sendArrayResults(result); } else if (Iterable.class.isAssignableFrom(result.getClass())) { - new BatchingResultSender(batchSize, resultSender).sendResults((Iterable) result); + new BatchingResultSender(this.batchSize, resultSender).sendResults((Iterable) result); } else { resultSender.lastResult(result); diff --git a/src/main/java/org/springframework/data/gemfire/function/config/AbstractFunctionExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/AbstractFunctionExecutionBeanDefinitionBuilder.java index 2ba64d5d..5344358b 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/AbstractFunctionExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/AbstractFunctionExecutionBeanDefinitionBuilder.java @@ -1,17 +1,20 @@ /* * Copyright 2002-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.config; +import java.util.Optional; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; @@ -35,40 +38,37 @@ abstract class AbstractFunctionExecutionBeanDefinitionBuilder { protected final Log log = LogFactory.getLog(getClass()); /** - * * @param configuration the configuration values */ - AbstractFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { - Assert.notNull(configuration); + AbstractFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + Assert.notNull(configuration, "Configuration must not be null"); this.configuration = configuration; } - + /** * Build the bean definition - * @param registry - * @return */ - BeanDefinition build(BeanDefinitionRegistry registry) { + BeanDefinition build(BeanDefinitionRegistry registry) { BeanDefinitionBuilder functionProxyFactoryBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition( getFunctionProxyFactoryBeanClass()); - functionProxyFactoryBeanBuilder.addConstructorArgValue(configuration.getFunctionExecutionInterface()); + functionProxyFactoryBeanBuilder.addConstructorArgValue(this.configuration.getFunctionExecutionInterface()); functionProxyFactoryBeanBuilder.addConstructorArgReference(BeanDefinitionReaderUtils.registerWithGeneratedName( buildGemfireFunctionOperations(registry), registry)); - + return functionProxyFactoryBeanBuilder.getBeanDefinition(); - } + } protected AbstractBeanDefinition buildGemfireFunctionOperations(BeanDefinitionRegistry registry) { + BeanDefinitionBuilder functionTemplateBuilder = getGemfireFunctionOperationsBeanDefinitionBuilder(registry); functionTemplateBuilder.setLazyInit(true); - String resultCollectorReference = (String) configuration.getAttribute("resultCollector"); - - if (StringUtils.hasText(resultCollectorReference)){ - functionTemplateBuilder.addPropertyReference("resultCollector", resultCollectorReference); - } + Optional.ofNullable(this.configuration.getAttribute("resultCollector")) + .map(String::valueOf) + .filter(StringUtils::hasText) + .ifPresent(reference -> functionTemplateBuilder.addPropertyReference("resultCollector", reference)); return functionTemplateBuilder.getBeanDefinition(); } diff --git a/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionBuilderFactory.java b/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionBuilderFactory.java index 61c135c9..7ac42d4c 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionBuilderFactory.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionBuilderFactory.java @@ -1,11 +1,11 @@ /* * Copyright 2002-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. @@ -28,11 +28,11 @@ import org.springframework.data.gemfire.function.annotation.OnServers; * @see org.springframework.data.gemfire.function.annotation.OnRegion * @see org.springframework.data.gemfire.function.annotation.OnServer * @see org.springframework.data.gemfire.function.annotation.OnServers - * @see org.springframework.data.gemfire.function.config.OnMemberExecutionBeanDefinitionBuilder - * @see org.springframework.data.gemfire.function.config.OnMembersExecutionBeanDefinitionBuilder - * @see org.springframework.data.gemfire.function.config.OnRegionExecutionBeanDefinitionBuilder - * @see org.springframework.data.gemfire.function.config.OnServerExecutionBeanDefinitionBuilder - * @see org.springframework.data.gemfire.function.config.OnServersExecutionBeanDefinitionBuilder + * @see OnMemberFunctionExecutionBeanDefinitionBuilder + * @see OnMembersFunctionExecutionBeanDefinitionBuilder + * @see OnRegionFunctionExecutionBeanDefinitionBuilder + * @see OnServerFunctionExecutionBeanDefinitionBuilder + * @see OnServersFunctionExecutionBeanDefinitionBuilder */ abstract class FunctionExecutionBeanDefinitionBuilderFactory { @@ -40,22 +40,21 @@ abstract class FunctionExecutionBeanDefinitionBuilderFactory { String functionExecutionAnnotation = configuration.getAnnotationType(); if (OnMember.class.getName().equals(functionExecutionAnnotation)) { - return new OnMemberExecutionBeanDefinitionBuilder(configuration); + return new OnMemberFunctionExecutionBeanDefinitionBuilder(configuration); } else if (OnMembers.class.getName().equals(functionExecutionAnnotation)) { - return new OnMembersExecutionBeanDefinitionBuilder(configuration); + return new OnMembersFunctionExecutionBeanDefinitionBuilder(configuration); } else if (OnRegion.class.getName().equals(functionExecutionAnnotation)) { - return new OnRegionExecutionBeanDefinitionBuilder(configuration); - } + return new OnRegionFunctionExecutionBeanDefinitionBuilder(configuration); + } else if (OnServer.class.getName().equals(functionExecutionAnnotation)) { - return new OnServerExecutionBeanDefinitionBuilder(configuration); - } + return new OnServerFunctionExecutionBeanDefinitionBuilder(configuration); + } else if (OnServers.class.getName().equals(functionExecutionAnnotation)) { - return new OnServersExecutionBeanDefinitionBuilder(configuration); + return new OnServersFunctionExecutionBeanDefinitionBuilder(configuration); } return null; } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionRegistrar.java b/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionRegistrar.java index 3883c761..c6b88bc6 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionRegistrar.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionBeanDefinitionRegistrar.java @@ -109,17 +109,19 @@ public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefin Set annotationTypes = beanDefinition.getMetadata().getAnnotationTypes(); - String functionExecutionAnnotation = null; + String existingFunctionExecutionAnnotation = null; for (String annotationType : annotationTypes) { if (functionExecutionAnnotationTypeNames.contains(annotationType)) { - Assert.isNull(functionExecutionAnnotation, String.format( - "interface %1$s contains multiple Function Execution Annotations: %2$s, %3$s", - beanDefinition.getBeanClassName(), functionExecutionAnnotation, annotationType)); - functionExecutionAnnotation = annotationType; + + Assert.isNull(existingFunctionExecutionAnnotation, + String.format("Interface [%1$s] contains multiple Function Execution Annotations: %2$s, %3$s", + beanDefinition.getBeanClassName(), existingFunctionExecutionAnnotation, annotationType)); + + existingFunctionExecutionAnnotation = annotationType; } } - return functionExecutionAnnotation; + return existingFunctionExecutionAnnotation; } } diff --git a/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionConfiguration.java b/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionConfiguration.java index 541d7250..dbd1461b 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/FunctionExecutionConfiguration.java @@ -1,72 +1,81 @@ /* * Copyright 2002-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.config; -import java.util.Map; - import org.springframework.context.annotation.ScannedGenericBeanDefinition; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.data.gemfire.util.SpringUtils; import org.springframework.util.Assert; /** * Function execution configuration used by bean definition builders - * + * * @author David Turanski * @author John Blum */ class FunctionExecutionConfiguration { - + private Class functionExecutionInterface; - private final Map attributes; + private final AnnotationAttributes annotationAttributes; private final String annotationType; - /* constructor for testing purposes only! */ + /* constructor for testing purposes only */ FunctionExecutionConfiguration() { this.annotationType = null; - this.attributes = null; + this.annotationAttributes = null; } FunctionExecutionConfiguration(ScannedGenericBeanDefinition beanDefinition, String annotationType) { try { - this.annotationType = annotationType; - this.attributes = beanDefinition.getMetadata().getAnnotationAttributes(annotationType, true); - this.functionExecutionInterface = beanDefinition.resolveBeanClass(beanDefinition.getClass().getClassLoader()); - Assert.isTrue(functionExecutionInterface.isInterface(), - String.format("The annotation %1$s only applies to an interface. It is not valid for the type %2$s", - annotationType, functionExecutionInterface.getName())); - + this.annotationType = annotationType; + + this.annotationAttributes = AnnotationAttributes.fromMap(beanDefinition.getMetadata() + .getAnnotationAttributes(annotationType, true)); + + this.functionExecutionInterface = + beanDefinition.resolveBeanClass(beanDefinition.getClass().getClassLoader()); + + assertFunctionExecutionInterfaceIsValid(annotationType); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } + private void assertFunctionExecutionInterfaceIsValid(String annotationType) { + + boolean valid = this.functionExecutionInterface != null && this.functionExecutionInterface.isInterface(); + + Assert.isTrue(valid, String.format("The annotation [%1$s] only applies to an interface; It is not valid for type [%2$s]", + annotationType, SpringUtils.nullSafeName(this.functionExecutionInterface))); + } + String getAnnotationType() { return this.annotationType; } Object getAttribute(String name) { - return attributes.get(name); + return this.annotationAttributes.get(name); } - Map getAttributes() { - return this.attributes; + AnnotationAttributes getAttributes() { + return this.annotationAttributes; } Class getFunctionExecutionInterface() { return this.functionExecutionInterface; } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/config/MemberBasedExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/MemberBasedFunctionExecutionBeanDefinitionBuilder.java similarity index 79% rename from src/main/java/org/springframework/data/gemfire/function/config/MemberBasedExecutionBeanDefinitionBuilder.java rename to src/main/java/org/springframework/data/gemfire/function/config/MemberBasedFunctionExecutionBeanDefinitionBuilder.java index 3c092417..c27b0490 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/MemberBasedExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/MemberBasedFunctionExecutionBeanDefinitionBuilder.java @@ -10,8 +10,11 @@ * 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.config; +import java.util.Optional; + import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.data.gemfire.function.annotation.OnMember; @@ -27,13 +30,15 @@ import org.springframework.util.StringUtils; * @author John Blum * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder */ -abstract class MemberBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder { +abstract class MemberBasedFunctionExecutionBeanDefinitionBuilder + extends AbstractFunctionExecutionBeanDefinitionBuilder { - MemberBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + MemberBasedFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { super(configuration); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry) */ @Override @@ -42,17 +47,19 @@ abstract class MemberBasedExecutionBeanDefinitionBuilder extends AbstractFunctio BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(getGemfireOperationsClass()); - String groups = (String)configuration.getAttribute("groups"); - - if (StringUtils.hasText(groups)) { - functionTemplateBuilder.addConstructorArgValue(StringUtils.commaDelimitedListToStringArray(groups)); - } + Optional.ofNullable(this.configuration.getAttribute("groups")) + .map(String::valueOf) + .map(StringUtils::trimAllWhitespace) + .filter(StringUtils::hasText) + .map(StringUtils::commaDelimitedListToStringArray) + .ifPresent(functionTemplateBuilder::addConstructorArgValue); return functionTemplateBuilder; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass() */ @Override diff --git a/src/main/java/org/springframework/data/gemfire/function/config/OnMemberExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/OnMemberFunctionExecutionBeanDefinitionBuilder.java similarity index 73% rename from src/main/java/org/springframework/data/gemfire/function/config/OnMemberExecutionBeanDefinitionBuilder.java rename to src/main/java/org/springframework/data/gemfire/function/config/OnMemberFunctionExecutionBeanDefinitionBuilder.java index af323286..4d2592bb 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/OnMemberExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/OnMemberFunctionExecutionBeanDefinitionBuilder.java @@ -1,36 +1,33 @@ /* * Copyright 2002-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.config; import org.springframework.data.gemfire.function.execution.GemfireOnMemberFunctionTemplate; /** - * * @author David Turanski - * + * @author John Blum */ -class OnMemberExecutionBeanDefinitionBuilder extends MemberBasedExecutionBeanDefinitionBuilder { +class OnMemberFunctionExecutionBeanDefinitionBuilder extends MemberBasedFunctionExecutionBeanDefinitionBuilder { - /** - * @param configuration - */ - OnMemberExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + OnMemberFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { super(configuration); - // TODO Auto-generated constructor stub } - /* (non-Javadoc) - * @see org.springframework.data.gemfire.function.config.MemberBasedExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsClass() + /* + * (non-Javadoc) + * @see org.springframework.data.gemfire.function.config.MemberBasedFunctionExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsClass() */ @Override protected Class getGemfireOperationsClass() { diff --git a/src/main/java/org/springframework/data/gemfire/function/config/OnMembersExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/OnMembersFunctionExecutionBeanDefinitionBuilder.java similarity index 73% rename from src/main/java/org/springframework/data/gemfire/function/config/OnMembersExecutionBeanDefinitionBuilder.java rename to src/main/java/org/springframework/data/gemfire/function/config/OnMembersFunctionExecutionBeanDefinitionBuilder.java index f8820cdd..d2bc2a0b 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/OnMembersExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/OnMembersFunctionExecutionBeanDefinitionBuilder.java @@ -1,39 +1,36 @@ /* * Copyright 2002-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.config; import org.springframework.data.gemfire.function.execution.GemfireOnMembersFunctionTemplate; /** * @author David Turanski - * + * @author John Blum */ -class OnMembersExecutionBeanDefinitionBuilder extends MemberBasedExecutionBeanDefinitionBuilder { +class OnMembersFunctionExecutionBeanDefinitionBuilder extends MemberBasedFunctionExecutionBeanDefinitionBuilder { - /** - * @param configuration - */ - OnMembersExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + OnMembersFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { super(configuration); - // TODO Auto-generated constructor stub } - /* (non-Javadoc) - * @see org.springframework.data.gemfire.function.config.MemberBasedExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsClass() + /* + * (non-Javadoc) + * @see org.springframework.data.gemfire.function.config.MemberBasedFunctionExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsClass() */ @Override protected Class getGemfireOperationsClass() { return GemfireOnMembersFunctionTemplate.class; } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/config/OnRegionExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/OnRegionFunctionExecutionBeanDefinitionBuilder.java similarity index 64% rename from src/main/java/org/springframework/data/gemfire/function/config/OnRegionExecutionBeanDefinitionBuilder.java rename to src/main/java/org/springframework/data/gemfire/function/config/OnRegionFunctionExecutionBeanDefinitionBuilder.java index 8a14f24f..f672f577 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/OnRegionExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/OnRegionFunctionExecutionBeanDefinitionBuilder.java @@ -1,15 +1,16 @@ /* * Copyright 2002-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.config; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -21,34 +22,38 @@ import org.springframework.data.gemfire.function.execution.OnRegionFunctionProxy * @author David Turanski * */ -class OnRegionExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder { +class OnRegionFunctionExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder { - /** - * @param configuration - */ - OnRegionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + OnRegionFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { super(configuration); } - - - /* (non-Javadoc) - * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry) + /* + * (non-Javadoc) + * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder + * #getGemfireFunctionOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry) */ @Override protected BeanDefinitionBuilder getGemfireFunctionOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) { - BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(GemfireOnRegionFunctionTemplate.class); - functionTemplateBuilder.addConstructorArgReference((String)configuration.getAttribute("region")); + + BeanDefinitionBuilder functionTemplateBuilder = + BeanDefinitionBuilder.genericBeanDefinition(GemfireOnRegionFunctionTemplate.class); + + String regionBeanName = String.valueOf(this.configuration.getAttribute("region")); + + functionTemplateBuilder.addConstructorArgReference(regionBeanName); + return functionTemplateBuilder; } - /* (non-Javadoc) - * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass() + /* + * (non-Javadoc) + * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder + * #getFunctionProxyFactoryBeanClass() */ @Override protected Class getFunctionProxyFactoryBeanClass() { return OnRegionFunctionProxyFactoryBean.class; } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/config/OnServerExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/OnServerFunctionExecutionBeanDefinitionBuilder.java similarity index 79% rename from src/main/java/org/springframework/data/gemfire/function/config/OnServerExecutionBeanDefinitionBuilder.java rename to src/main/java/org/springframework/data/gemfire/function/config/OnServerFunctionExecutionBeanDefinitionBuilder.java index 396b35ab..2a1daa8b 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/OnServerExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/OnServerFunctionExecutionBeanDefinitionBuilder.java @@ -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.config; import org.springframework.data.gemfire.function.execution.GemfireOnServerFunctionTemplate; @@ -18,19 +19,19 @@ import org.springframework.data.gemfire.function.execution.GemfireOnServerFuncti * @author David Turanski * @author John Blum */ -class OnServerExecutionBeanDefinitionBuilder extends ServerBasedExecutionBeanDefinitionBuilder { +class OnServerFunctionExecutionBeanDefinitionBuilder extends ServerBasedFunctionExecutionBeanDefinitionBuilder { - OnServerExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + OnServerFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { super(configuration); } - /* (non-Javadoc) - * @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder + /* + * (non-Javadoc) + * @see org.springframework.data.gemfire.function.config.ServerBasedFunctionExecutionBeanDefinitionBuilder * #getGemfireFunctionOperationsClass() */ @Override protected Class getGemfireFunctionOperationsClass() { return GemfireOnServerFunctionTemplate.class; } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/config/OnServersExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/OnServersFunctionExecutionBeanDefinitionBuilder.java similarity index 74% rename from src/main/java/org/springframework/data/gemfire/function/config/OnServersExecutionBeanDefinitionBuilder.java rename to src/main/java/org/springframework/data/gemfire/function/config/OnServersFunctionExecutionBeanDefinitionBuilder.java index 6cdf4cda..7163c884 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/OnServersExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/OnServersFunctionExecutionBeanDefinitionBuilder.java @@ -10,25 +10,25 @@ * 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.config; import org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate; /** * @author David Turanski - * + * @author John Blum */ -class OnServersExecutionBeanDefinitionBuilder extends ServerBasedExecutionBeanDefinitionBuilder { +class OnServersFunctionExecutionBeanDefinitionBuilder extends ServerBasedFunctionExecutionBeanDefinitionBuilder { - /** - * @param configuration - */ - OnServersExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + OnServersFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { super(configuration); } - /* (non-Javadoc) - * @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder#getGemfireFunctionOperationsClass() + /* + * (non-Javadoc) + * @see org.springframework.data.gemfire.function.config.ServerBasedFunctionExecutionBeanDefinitionBuilder + * #getGemfireFunctionOperationsClass() */ @Override protected Class getGemfireFunctionOperationsClass() { diff --git a/src/main/java/org/springframework/data/gemfire/function/config/ServerBasedExecutionBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/gemfire/function/config/ServerBasedFunctionExecutionBeanDefinitionBuilder.java similarity index 66% rename from src/main/java/org/springframework/data/gemfire/function/config/ServerBasedExecutionBeanDefinitionBuilder.java rename to src/main/java/org/springframework/data/gemfire/function/config/ServerBasedFunctionExecutionBeanDefinitionBuilder.java index 60973e23..f5b78e8d 100644 --- a/src/main/java/org/springframework/data/gemfire/function/config/ServerBasedExecutionBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/gemfire/function/config/ServerBasedFunctionExecutionBeanDefinitionBuilder.java @@ -12,13 +12,14 @@ */ package org.springframework.data.gemfire.function.config; +import java.util.Optional; + import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.data.gemfire.config.xml.GemfireConstants; import org.springframework.data.gemfire.function.annotation.OnServer; import org.springframework.data.gemfire.function.annotation.OnServers; import org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean; -import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -27,38 +28,51 @@ import org.springframework.util.StringUtils; * * @author David Turanski * @author John Blum + * @see org.springframework.beans.factory.support.BeanDefinitionBuilder + * @see org.springframework.beans.factory.support.BeanDefinitionRegistry + * @see org.springframework.data.gemfire.function.annotation.OnServer + * @see org.springframework.data.gemfire.function.annotation.OnServers * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder */ -abstract class ServerBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder { +abstract class ServerBasedFunctionExecutionBeanDefinitionBuilder + extends AbstractFunctionExecutionBeanDefinitionBuilder { - ServerBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + ServerBasedFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { super(configuration); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder * #getGemfireFunctionOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry) */ @Override protected BeanDefinitionBuilder getGemfireFunctionOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) { + String resolvedCacheBeanName = Optional.ofNullable(this.configuration.getAttribute("cache")) + .map(String::valueOf) + .filter(StringUtils::hasText) + .orElse(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME); + + Optional poolBeanName = Optional.ofNullable(this.configuration.getAttribute("pool")) + .map(String::valueOf) + .filter(StringUtils::hasText); + BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(getGemfireFunctionOperationsClass()); - String cache = (String) this.configuration.getAttribute("cache"); - String pool = (String) this.configuration.getAttribute("pool"); + functionTemplateBuilder.addConstructorArgReference(resolvedCacheBeanName); - Assert.state(!(StringUtils.hasText(cache) && StringUtils.hasText(pool)), - String.format("Invalid configuration for interface [%s]; cannot specify both 'pool' and 'cache'", - this.configuration.getFunctionExecutionInterface().getName())); - - functionTemplateBuilder.addConstructorArgReference(StringUtils.hasText(pool) - ? pool : (StringUtils.hasText(cache) ? cache : GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME)); + poolBeanName.ifPresent(it -> { + functionTemplateBuilder.addDependsOn(it); + functionTemplateBuilder.addPropertyReference("pool", it); + }); return functionTemplateBuilder; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder * #getFunctionProxyFactoryBeanClass() */ diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionTemplate.java b/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionTemplate.java index b4d7c42e..9ca29c8f 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionTemplate.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/AbstractFunctionTemplate.java @@ -10,29 +10,32 @@ * 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.execution; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.geode.cache.execute.Function; import org.apache.geode.cache.execute.ResultCollector; +import org.springframework.beans.factory.InitializingBean; /** - * The base class for GemFire FunctionTemplates used to invoke GemFire Functions. + * The base class for {@link Function} templates used to invoke Apache Geode/Pivotal GemFire {@link Function Functions}. * * @author David Turanski * @author John Blum * @see org.apache.geode.cache.execute.Function * @see org.apache.geode.cache.execute.ResultCollector + * @see org.springframework.beans.factory.InitializingBean + * @see org.springframework.data.gemfire.function.execution.GemfireFunctionOperations */ -abstract class AbstractFunctionTemplate implements GemfireFunctionOperations { - - protected Log log = LogFactory.getLog(this.getClass()); +abstract class AbstractFunctionTemplate implements GemfireFunctionOperations, InitializingBean { protected long timeout; protected volatile ResultCollector resultCollector; + @Override + public void afterPropertiesSet() throws Exception { } + @Override public Iterable execute(Function function, Object... args) { return execute(getFunctionExecution().setArgs(args).setFunction(function)); diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java index d8d2fed0..52620e8d 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBean.java @@ -1,11 +1,11 @@ /* * Copyright 2002-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. @@ -16,8 +16,8 @@ import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanClassLoaderAware; @@ -27,7 +27,7 @@ import org.springframework.util.ClassUtils; /** * A Proxy FactoryBean for all non-Region Function Execution interfaces. - * + * * @author David Turanski * @author John Blum * @see java.lang.reflect.Method @@ -47,7 +47,7 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean, Met private final GemfireFunctionOperations gemfireFunctionOperations; - protected Log logger = LogFactory.getLog(this.getClass()); + protected Logger logger = LoggerFactory.getLogger(this.getClass()); private FunctionExecutionMethodMetadata methodMetadata; @@ -56,8 +56,12 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean, Met * @param gemfireFunctionOperations an interface used to delegate the function invocation (typically a GemFire function template) */ public GemfireFunctionProxyFactoryBean(Class functionExecutionInterface, GemfireFunctionOperations gemfireFunctionOperations) { - Assert.notNull(functionExecutionInterface, "'functionExecutionInterface' must not be null"); - Assert.isTrue(functionExecutionInterface.isInterface(), "'functionExecutionInterface' must be an interface"); + + Assert.notNull(functionExecutionInterface, "Function execution interface must not be null"); + + Assert.isTrue(functionExecutionInterface.isInterface(), + String.format("Function execution type [%s] must be an interface", + functionExecutionInterface.getClass().getName())); this.functionExecutionInterface = functionExecutionInterface; this.gemfireFunctionOperations = gemfireFunctionOperations; @@ -76,26 +80,27 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean, Met @Override public Object invoke(MethodInvocation invocation) throws Throwable { if (AopUtils.isToStringMethod(invocation.getMethod())) { - return "GemFire Function Proxy for service interface [" + this.functionExecutionInterface + "]"; + return String.format("Function Proxy for interface [%s]", this.functionExecutionInterface.getName()); } if (logger.isDebugEnabled()) { - logger.debug("invoking method " + invocation.getMethod().getName()); + logger.debug("Invoking method {}", invocation.getMethod().getName()); } return invokeFunction(invocation.getMethod(), invocation.getArguments()); } protected Object invokeFunction(Method method, Object[] args) { - return this.gemfireFunctionOperations.executeAndExtract( - methodMetadata.getMethodMetadata(method).getFunctionId(), args); + + return this.gemfireFunctionOperations + .executeAndExtract(this.methodMetadata.getMethodMetadata(method).getFunctionId(), args); } @Override public Object getObject() throws Exception { if (functionExecutionProxy == null) { onInit(); - Assert.notNull(functionExecutionProxy, "failed to initialize proxy"); + Assert.notNull(this.functionExecutionProxy, "Failed to initialize Function Proxy"); } return functionExecutionProxy; @@ -118,5 +123,4 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean, Met initialized = true; } } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionFunctionTemplate.java b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionFunctionTemplate.java index e3263fb6..f55a6b26 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionFunctionTemplate.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionFunctionTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2018 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 @@ -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.execution; import java.util.Set; @@ -20,50 +21,58 @@ import org.springframework.util.Assert; /** * @author David Turanski - * + * @author John Blum */ public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations { - private Region region; + private final Region region; /** - * Constructs an instance of the GemFireOnRegionFunctionTemplate with the given GemFire Cache Region. + * Constructs a new instance of the {@link GemfireOnRegionFunctionTemplate} initialized with + * the given {@link Region}. * - * @param region the GemFire Cache Region upon which the Function will be executed. + * @param region the {@link Region} upon which the {@link Function} will be executed. + * @throws IllegalArgumentException if {@link Region} is {@literal null}. * @see org.apache.geode.cache.Region */ public GemfireOnRegionFunctionTemplate(Region region) { - Assert.notNull(region, "Region cannot be null"); + + Assert.notNull(region, "Region must not be null"); + this.region = region; } @Override - public Iterable execute(Function function, Set keys, Object... args) { - return execute(new RegionFunctionExecution(region).setKeys(keys).setFunction(function).setTimeout(timeout) - .setArgs(args)); - } - - @Override - public Iterable execute(String functionId, Set keys, Object... args) { - return execute(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId).setTimeout(timeout) - .setArgs(args)); - } - - @Override - public T executeAndextract(String functionId, Set keys, Object... args) { - return this. executeAndExtract(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId) - .setTimeout(timeout).setArgs(args)); - } - - @Override - protected AbstractFunctionExecution getFunctionExecution() { + protected RegionFunctionExecution 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); + public Iterable execute(String functionId, Set keys, Object... args) { + + return execute(getFunctionExecution() + .setKeys(keys) + .setFunctionId(functionId) + .setTimeout(this.timeout) + .setArgs(args)); } + @Override + public T executeAndExtract(String functionId, Set keys, Object... args) { + + return executeAndExtract(getFunctionExecution() + .setKeys(keys) + .setFunctionId(functionId) + .setTimeout(this.timeout).setArgs(args)); + } + + @Override + public void executeWithNoResult(String functionId, Set keys, Object... args) { + + execute(getFunctionExecution() + .setKeys(keys) + .setFunctionId(functionId) + .setTimeout(this.timeout) + .setArgs(args), false); + } } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionOperations.java b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionOperations.java index f6ca87b3..1b6bc19e 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionOperations.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnRegionOperations.java @@ -10,20 +10,42 @@ * 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.execution; import java.util.Set; +import org.apache.geode.cache.Region; import org.apache.geode.cache.execute.Function; /** + * Interface define {@link Region} {@link Function} data access operations. + * * @author David Turanski + * @author John Blum + * @see org.apache.geode.cache.Region + * @see org.apache.geode.cache.execute.Function + * @see org.springframework.data.gemfire.function.execution.GemfireFunctionOperations */ +@SuppressWarnings("unused") public interface GemfireOnRegionOperations extends GemfireFunctionOperations { - public abstract Iterable execute(String functionId, Set keys, Object... args); - public abstract Iterable execute(Function function, Set keys, Object... args); - public abstract void executeWithNoResult(String functionId, Set keys, Object... args); - public abstract T executeAndextract(String functionId, Set keys, Object... args); + default Iterable execute(Function function, Set keys, Object... args) { + return execute(function.getId(), keys, args); + } + + Iterable execute(String functionId, Set keys, Object... args); + + default T executeAndExtract(Function function, Set keys, Object... args) { + return executeAndExtract(function.getId(), keys, args); + } + + T executeAndExtract(String functionId, Set keys, Object... args); + + default void executeWithNoResult(Function function, Set keys, Object... args) { + executeWithNoResult(function.getId(), keys, args); + } + + void executeWithNoResult(String functionId, Set keys, Object... args); } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServerFunctionTemplate.java b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServerFunctionTemplate.java index 5ebe4fd2..cdf698e3 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServerFunctionTemplate.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServerFunctionTemplate.java @@ -13,31 +13,110 @@ package org.springframework.data.gemfire.function.execution; +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException; + +import java.util.Optional; + import org.apache.geode.cache.RegionService; +import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.Pool; +import org.apache.geode.cache.client.PoolManager; +import org.apache.geode.cache.execute.Execution; +import org.apache.geode.cache.execute.Function; +import org.apache.shiro.util.Assert; +import org.springframework.data.gemfire.GemfireUtils; +import org.springframework.data.gemfire.util.CacheUtils; +import org.springframework.util.StringUtils; /** + * Creates an {@literal OnServer} {@link Function} {@link Execution} initialized with + * either a {@link RegionService cache} or a {@link Pool}. + * * @author David Turanski * @author John Blum + * @see org.apache.geode.cache.RegionService + * @see org.apache.geode.cache.client.ClientCache + * @see org.apache.geode.cache.client.Pool + * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.Function + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionTemplate */ -public class GemfireOnServerFunctionTemplate extends AbstractFunctionTemplate { +@SuppressWarnings("unused") +public class GemfireOnServerFunctionTemplate extends AbstractFunctionTemplate { + + private Pool pool; - private final Pool pool; private final RegionService cache; + private String poolName; + public GemfireOnServerFunctionTemplate(RegionService cache) { + + Assert.notNull(cache, "RegionService must not be null"); + this.cache = cache; - this.pool = null; } public GemfireOnServerFunctionTemplate(Pool pool) { - this.cache = null; + this.cache = resolveClientCache(); this.pool = pool; } + public GemfireOnServerFunctionTemplate(String poolName) { + this.cache = resolveClientCache(); + this.poolName = poolName; + } + + public void setPool(Pool pool) { + this.pool = pool; + } + + public void setPoolName(String poolName) { + this.poolName = poolName; + } + @Override protected AbstractFunctionExecution getFunctionExecution() { - return (pool != null ? new PoolServerFunctionExecution(this.pool) : new ServerFunctionExecution(this.cache)); + + Object gemfireObject = resolveRequiredGemFireObject(); + + return gemfireObject instanceof Pool + ? new PoolServerFunctionExecution((Pool) gemfireObject) + : new ServerFunctionExecution((RegionService) gemfireObject); } + private Object resolveRequiredGemFireObject() { + return Optional.ofNullable(resolvePool()).orElseGet(this::resolveClientCache); + } + + protected ClientCache resolveClientCache() { + + return Optional.ofNullable(CacheUtils.getClientCache()) + .orElseThrow(() -> newIllegalStateException("No ClientCache instance is present")); + } + + protected Pool resolveDefaultPool() { + + return Optional.ofNullable(PoolManager.find(GemfireUtils.DEFAULT_POOL_NAME)) + .orElseThrow(() -> newIllegalStateException("No Pool was configured")); + } + + protected Pool resolveNamedPool() { + + if (StringUtils.hasText(this.poolName)) { + this.pool = Optional.ofNullable(PoolManager.find(this.poolName)) + .orElseThrow(() -> newIllegalStateException("No Pool with name [%s] exists", + this.poolName)); + } + + return this.pool; + } + + protected Pool resolvePool() { + + this.pool = Optional.ofNullable(this.pool) + .orElseGet(this::resolveNamedPool); + + return this.pool; + } } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServersFunctionTemplate.java b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServersFunctionTemplate.java index 7f0e1a0d..82a1c825 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServersFunctionTemplate.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/GemfireOnServersFunctionTemplate.java @@ -13,35 +13,110 @@ package org.springframework.data.gemfire.function.execution; +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException; + +import java.util.Optional; + import org.apache.geode.cache.RegionService; +import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.Pool; +import org.apache.geode.cache.client.PoolManager; +import org.apache.geode.cache.execute.Execution; +import org.apache.geode.cache.execute.Function; +import org.springframework.data.gemfire.GemfireUtils; +import org.springframework.data.gemfire.util.CacheUtils; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** - * @author David Turanski + * Creates an {@literal OnServers} {@link Function} {@link Execution} initialized with + * either a {@link RegionService cache} or a {@link Pool}. * + * @author David Turanski + * @author John Blum + * @see org.apache.geode.cache.RegionService + * @see org.apache.geode.cache.client.ClientCache + * @see org.apache.geode.cache.client.Pool + * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.Function + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionTemplate */ -public class GemfireOnServersFunctionTemplate extends AbstractFunctionTemplate { +@SuppressWarnings("unused") +public class GemfireOnServersFunctionTemplate extends AbstractFunctionTemplate { + + private Pool pool; private final RegionService cache; - private final Pool pool; + private String poolName; + + public GemfireOnServersFunctionTemplate(RegionService cache) { + + Assert.notNull(cache, "RegionService must not be null"); - public GemfireOnServersFunctionTemplate (RegionService cache) { this.cache = cache; - this.pool = null; } - public GemfireOnServersFunctionTemplate (Pool pool) { + public GemfireOnServersFunctionTemplate(Pool pool) { + this.cache = resolveClientCache(); this.pool = pool; - this.cache = null; + } + + public GemfireOnServersFunctionTemplate(String poolName) { + this.cache = resolveClientCache(); + this.poolName = poolName; + } + + public void setPool(Pool pool) { + this.pool = pool; + } + + public void setPoolName(String poolName) { + this.poolName = poolName; } @Override protected AbstractFunctionExecution getFunctionExecution() { - if (this.pool == null) { - return new ServersFunctionExecution(this.cache); - } - return new PoolServersFunctionExecution(this.pool); + + Object gemfireObject = resolveRequiredGemFireObject(); + + return gemfireObject instanceof Pool + ? new PoolServersFunctionExecution((Pool) gemfireObject) + : new ServersFunctionExecution((RegionService) gemfireObject); } + protected Object resolveRequiredGemFireObject() { + return Optional.ofNullable(resolvePool()).orElseGet(this::resolveClientCache); + } + + protected ClientCache resolveClientCache() { + + return Optional.ofNullable(CacheUtils.getClientCache()) + .orElseThrow(() -> newIllegalStateException("No ClientCache instance is present")); + } + + protected Pool resolveDefaultPool() { + + return Optional.ofNullable(PoolManager.find(GemfireUtils.DEFAULT_POOL_NAME)) + .orElseThrow(() -> newIllegalStateException("No Pool was configured")); + } + + protected Pool resolveNamedPool() { + + if (StringUtils.hasText(this.poolName)) { + this.pool = Optional.ofNullable(PoolManager.find(this.poolName)) + .orElseThrow(() -> newIllegalStateException("No Pool with name [%s] exists", + this.poolName)); + } + + return this.pool; + } + + protected Pool resolvePool() { + + this.pool = Optional.ofNullable(this.pool) + .orElseGet(this::resolveNamedPool); + + return this.pool; + } } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/GroupMemberFunctionExecution.java b/src/main/java/org/springframework/data/gemfire/function/execution/GroupMemberFunctionExecution.java index 7fef164b..3e81171e 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/GroupMemberFunctionExecution.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/GroupMemberFunctionExecution.java @@ -10,35 +10,47 @@ * 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.execution; import org.apache.geode.cache.execute.Execution; +import org.apache.geode.cache.execute.Function; import org.apache.geode.cache.execute.FunctionService; import org.springframework.util.Assert; /** + * Constructs an {@link Execution} using {@link FunctionService#onMember(String...)}. + * * @author David Turanski * @author John Blum - * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.Function * @see org.apache.geode.cache.execute.FunctionService + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution */ class GroupMemberFunctionExecution extends AbstractFunctionExecution { private final String[] groups; /** - * Constructs an instance of the GroupMemberFunctionExecution class to execute a data independent Function - * on a single member from each of the specified groups. + * Constructs a new instance of the {@link GroupMemberFunctionExecution} initialized to execute a data independent + * {@link Function} on a single member from each of the specified groups. * - * @param groups the list of GemFire Groups from which to pick a member from each group on which to execute - * the data independent Function. + * @param groups array of {@link String groups} from which to pick a member from each group + * on which to execute the data independent {@link Function}. + * @throws IllegalArgumentException if {@link String groups} is {@literal null} or empty. */ - public GroupMemberFunctionExecution(final String... groups) { - Assert.notEmpty(groups, "'groups' cannot be null or empty."); + public GroupMemberFunctionExecution(String... groups) { + + Assert.notEmpty(groups, "Groups must not be null or empty"); + this.groups = groups; } + protected String[] getGroups() { + return this.groups; + } + /** * Executes the data independent Function on a single member from each of the specified groups. * @@ -47,7 +59,6 @@ class GroupMemberFunctionExecution extends AbstractFunctionExecution { */ @Override protected Execution getExecution() { - return FunctionService.onMember(this.groups); + return FunctionService.onMember(getGroups()); } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/GroupMembersFunctionExecution.java b/src/main/java/org/springframework/data/gemfire/function/execution/GroupMembersFunctionExecution.java index efc63e09..6731d4a4 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/GroupMembersFunctionExecution.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/GroupMembersFunctionExecution.java @@ -10,34 +10,47 @@ * 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.execution; import org.apache.geode.cache.execute.Execution; +import org.apache.geode.cache.execute.Function; import org.apache.geode.cache.execute.FunctionService; import org.springframework.util.Assert; /** + * Constructs an {@link Execution} using {@link FunctionService#onMembers(String...)}. + * * @author David Turanski * @author John Blum - * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.Function * @see org.apache.geode.cache.execute.FunctionService + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution */ class GroupMembersFunctionExecution extends AbstractFunctionExecution { private final String[] groups; /** - * Constructs an instance of the GroupMembersFunctionExecution class to execute a data independent Function - * on all members from each of the specified groups. + * Constructs a new instance of {@link GroupMembersFunctionExecution} initialized to execute a data independent + * {@link Function} on all members from each of the specified {@link String groups}. * - * @param groups the list of GemFire Groups indicating the members on which to execute the data independent Function. + * @param groups array of {@link String groups} indicating the members on which to execute + * the data independent {@link Function}. + * @throws IllegalArgumentException if {@link String groups} is {@literal null} or empty. */ - public GroupMembersFunctionExecution(final String... groups) { - Assert.notEmpty(groups, "'groups' cannot be null or empty."); + public GroupMembersFunctionExecution(String... groups) { + + Assert.notEmpty(groups, "Groups must not be null or empty"); + this.groups = groups; } + protected String[] getGroups() { + return this.groups; + } + /** * Executes the data independent Function on all members from each of the specified groups. * @@ -46,7 +59,6 @@ class GroupMembersFunctionExecution extends AbstractFunctionExecution { */ @Override protected Execution getExecution() { - return FunctionService.onMembers(this.groups); + return FunctionService.onMembers(getGroups()); } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/PoolServerFunctionExecution.java b/src/main/java/org/springframework/data/gemfire/function/execution/PoolServerFunctionExecution.java index 1e749b20..eab05a16 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/PoolServerFunctionExecution.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/PoolServerFunctionExecution.java @@ -10,57 +10,42 @@ * 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.execution; import org.apache.geode.cache.client.Pool; -import org.apache.geode.cache.client.PoolManager; import org.apache.geode.cache.execute.Execution; import org.apache.geode.cache.execute.FunctionService; -import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * Creates a GemFire {@link Execution} using {code}FunctionService.onServer(Pool pool){code} - * @author David Turanski + * Constructs an {@link Execution} using {@link FunctionService#onServer(Pool)}. * + * @author David Turanski + * @author John Blum + * @see org.apache.geode.cache.client.Pool + * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.FunctionService + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution */ -class PoolServerFunctionExecution extends AbstractFunctionExecution implements InitializingBean { +class PoolServerFunctionExecution extends AbstractFunctionExecution { + private final Pool pool; - private Pool pool; - private String poolname; + PoolServerFunctionExecution(Pool pool) { + Assert.notNull(pool, "Pool must not be null"); - /** - * @param pool the {@link Pool} - */ - public PoolServerFunctionExecution(Pool pool) { - super(); - Assert.notNull(pool, "pool cannot be null"); this.pool = pool; } - public PoolServerFunctionExecution(String poolname) { - super(); - Assert.notNull(poolname, "pool name cannot be null"); - this.poolname = poolname; - + protected Pool getPool() { + return this.pool; } @Override protected Execution getExecution() { - return FunctionService.onServer(this.pool); - } - - - /* (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - this.pool = PoolManager.find(poolname); - Assert.notNull(pool," pool " + poolname+ " does not exist"); - + return FunctionService.onServer(getPool()); } } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/PoolServersFunctionExecution.java b/src/main/java/org/springframework/data/gemfire/function/execution/PoolServersFunctionExecution.java index ac5b5415..6a37cbef 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/PoolServersFunctionExecution.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/PoolServersFunctionExecution.java @@ -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.execution; import org.apache.geode.cache.client.Pool; @@ -18,26 +19,32 @@ import org.apache.geode.cache.execute.FunctionService; import org.springframework.util.Assert; /** - * Creates a GemFire {@link Execution} using {code}FunctionService.onServers(Pool pool){code} - * @author David Turanski + * Constructs an {@link Execution} using {@link FunctionService#onServers(Pool)}. * + * @author David Turanski + * @author John Blum + * @see org.apache.geode.cache.client.Pool + * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.FunctionService + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution */ class PoolServersFunctionExecution extends AbstractFunctionExecution { - private final Pool pool; - /** - * @param pool the {@link Pool} - */ - public PoolServersFunctionExecution(Pool pool ) { - super(); - Assert.notNull(pool, "pool cannot be null"); + PoolServersFunctionExecution(Pool pool) { + + Assert.notNull(pool, "Pool must not be null"); + this.pool = pool; } + protected Pool getPool() { + return pool; + } + @Override protected Execution getExecution() { - return FunctionService.onServers(this.pool); + return FunctionService.onServers(getPool()); } } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/ServerFunctionExecution.java b/src/main/java/org/springframework/data/gemfire/function/execution/ServerFunctionExecution.java index e529c6f6..12279302 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/ServerFunctionExecution.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/ServerFunctionExecution.java @@ -10,30 +10,41 @@ * 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.execution; import org.apache.geode.cache.RegionService; import org.apache.geode.cache.execute.Execution; import org.apache.geode.cache.execute.FunctionService; -import org.springframework.util.Assert; +import org.apache.shiro.util.Assert; /** - * Creates a GemFire {@link Execution} using {code}FunctionService.onServer(RegionService regionService){code} - * @author David Turanski + * Constructs an {@link Execution} using {@link FunctionService#onServer(RegionService)}. * + * @author David Turanski + * @author John Blum + * @see org.apache.geode.cache.RegionService + * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.FunctionService + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution */ class ServerFunctionExecution extends AbstractFunctionExecution { private final RegionService regionService; - public ServerFunctionExecution(RegionService regionService) { + ServerFunctionExecution(RegionService regionService) { + Assert.notNull(regionService, "RegionService must not be null"); + this.regionService = regionService; } + protected RegionService getRegionService() { + return regionService; + } + @Override protected Execution getExecution() { - return FunctionService.onServer(this.regionService); + return FunctionService.onServer(getRegionService()); } - } diff --git a/src/main/java/org/springframework/data/gemfire/function/execution/ServersFunctionExecution.java b/src/main/java/org/springframework/data/gemfire/function/execution/ServersFunctionExecution.java index cf6104d3..c2d63f0b 100644 --- a/src/main/java/org/springframework/data/gemfire/function/execution/ServersFunctionExecution.java +++ b/src/main/java/org/springframework/data/gemfire/function/execution/ServersFunctionExecution.java @@ -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.execution; import org.apache.geode.cache.RegionService; @@ -18,29 +19,32 @@ import org.apache.geode.cache.execute.FunctionService; import org.springframework.util.Assert; /** - * Creates a GemFire {@link Execution} using {code}FunctionService.onServers(RegionService regionService){code} - * @author David Turanski + * Constructs an {@link Execution} using {@link FunctionService#onServers(RegionService)}. * + * @author David Turanski + * @author John Blum + * @see org.apache.geode.cache.RegionService + * @see org.apache.geode.cache.execute.Execution + * @see org.apache.geode.cache.execute.FunctionService + * @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution */ class ServersFunctionExecution extends AbstractFunctionExecution { - private final RegionService regionService; - /** - * - * @param regionService e.g., Cache,Client, or GemFireCache - * @param function - * @param args - */ - public ServersFunctionExecution(RegionService regionService ) { - super(); - Assert.notNull(regionService,"regionService cannot be null"); + ServersFunctionExecution(RegionService regionService) { + + Assert.notNull(regionService, "RegionService must not be null"); + this.regionService = regionService; } + protected RegionService getRegionService() { + return regionService; + } + @Override protected Execution getExecution() { - return FunctionService.onServers(this.regionService); + return FunctionService.onServers(getRegionService()); } } diff --git a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java index 11ebff48..2778f78d 100644 --- a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java @@ -105,6 +105,14 @@ public abstract class SpringUtils { return (obj1 != null && obj1.equals(obj2)); } + public static String nullSafeName(Class type) { + return type != null ? type.getName() : null; + } + + public static String nullSafeSimpleName(Class type) { + return type != null ? type.getSimpleName() : null; + } + public static T safeGetValue(Supplier valueSupplier) { return safeGetValue(valueSupplier, (T) null); } diff --git a/src/test/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplateUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplateUnitTests.java index 33da4092..c9369600 100644 --- a/src/test/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/admin/remote/FunctionGemfireAdminTemplateUnitTests.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -82,8 +83,8 @@ public class FunctionGemfireAdminTemplateUnitTests { this.template = spy(new FunctionGemfireAdminTemplate(this.mockClientCache)); - when(this.template.newGemfireFunctionOperations(any(ClientCache.class))) - .thenReturn(this.mockFunctionOperations); + doReturn(this.mockFunctionOperations).when(this.template) + .newGemfireFunctionOperations(any(ClientCache.class)); when(this.mockIndex.getName()).thenReturn("MockIndex"); when(this.mockRegion.getName()).thenReturn("MockRegion"); diff --git a/src/test/java/org/springframework/data/gemfire/function/config/MemberBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java b/src/test/java/org/springframework/data/gemfire/function/config/MemberBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java new file mode 100644 index 00000000..d693fc79 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/function/config/MemberBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2018 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.config; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; + +/** + * Unit tests for {@link MemberBasedFunctionExecutionBeanDefinitionBuilder}. + * + * @author John Blum + * @see org.junit.Test + * @see org.mockito.Mock + * @see org.mockito.Mockito + * @see org.mockito.junit.MockitoJUnitRunner + * @see org.springframework.data.gemfire.function.config.MemberBasedFunctionExecutionBeanDefinitionBuilder + * @since 1.0.0 + */ +@RunWith(MockitoJUnitRunner.class) +public class MemberBasedFunctionExecutionBeanDefinitionBuilderUnitTests { + + @Mock + private FunctionExecutionConfiguration mockFunctionExecutionConfiguration; + + private MemberBasedFunctionExecutionBeanDefinitionBuilder beanDefinitionBuilder; + + @Before + public void setup() { + this.beanDefinitionBuilder = + new TestMemberBasedFunctionExecutionBeanDefinitionBuilder(this.mockFunctionExecutionConfiguration); + } + + @Test + public void getGemfireFunctionOperationsBeanDefinitionBuilderIsSuccessful() { + + when(this.mockFunctionExecutionConfiguration.getAttribute(eq("groups"))) + .thenReturn(" TestGroupOne, TestGroupTwo "); + + BeanDefinitionBuilder builder = + this.beanDefinitionBuilder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); + + assertThat(builder).isNotNull(); + + BeanDefinition beanDefinition = builder.getRawBeanDefinition(); + + assertThat(beanDefinition).isNotNull(); + assertThat(beanDefinition.getBeanClassName()).isEqualTo(Object.class.getName()); + assertThat(beanDefinition.getConstructorArgumentValues().getArgumentCount()).isEqualTo(1); + + ConstructorArgumentValues.ValueHolder constructorArgumentValue = + beanDefinition.getConstructorArgumentValues().getArgumentValue(0, String[].class); + + assertThat(constructorArgumentValue).isNotNull(); + assertThat((String[]) constructorArgumentValue.getValue()).containsExactly("TestGroupOne", "TestGroupTwo"); + + verify(this.mockFunctionExecutionConfiguration, times(1)) + .getAttribute(eq("groups")); + } + + private static final class TestMemberBasedFunctionExecutionBeanDefinitionBuilder + extends MemberBasedFunctionExecutionBeanDefinitionBuilder { + + private TestMemberBasedFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) { + super(configuration); + } + + @Override + protected Class getGemfireOperationsClass() { + return Object.class; + } + } +} diff --git a/src/test/java/org/springframework/data/gemfire/function/config/ServerBasedExecutionBeanDefinitionBuilderTest.java b/src/test/java/org/springframework/data/gemfire/function/config/ServerBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java similarity index 52% rename from src/test/java/org/springframework/data/gemfire/function/config/ServerBasedExecutionBeanDefinitionBuilderTest.java rename to src/test/java/org/springframework/data/gemfire/function/config/ServerBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java index 04668ae4..483f3685 100644 --- a/src/test/java/org/springframework/data/gemfire/function/config/ServerBasedExecutionBeanDefinitionBuilderTest.java +++ b/src/test/java/org/springframework/data/gemfire/function/config/ServerBasedFunctionExecutionBeanDefinitionBuilderUnitTests.java @@ -16,40 +16,30 @@ package org.springframework.data.gemfire.function.config; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.data.gemfire.config.xml.GemfireConstants; /** - * The ServerBasedExecutionBeanDefinitionBuilderTest class is test suite of test cases testing the contract - * and functionality of the ServerBasedExecutionBeanDefinitionBuilder class. + * Unit tests for {@link ServerBasedFunctionExecutionBeanDefinitionBuilder}. * * @author John Blum * @see org.junit.Test * @see org.mockito.Mockito - * @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder + * @see org.springframework.data.gemfire.function.config.ServerBasedFunctionExecutionBeanDefinitionBuilder * @since 1.7.0 */ -public class ServerBasedExecutionBeanDefinitionBuilderTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); +public class ServerBasedFunctionExecutionBeanDefinitionBuilderUnitTests { @Test @SuppressWarnings("unchecked") @@ -59,11 +49,11 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration"); when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn(null); - when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(" "); + when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(""); when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class); - ServerBasedExecutionBeanDefinitionBuilder builder = - new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { + ServerBasedFunctionExecutionBeanDefinitionBuilder builder = + new ServerBasedFunctionExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { @Override protected Class getGemfireFunctionOperationsClass() { @@ -71,21 +61,25 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { } }; - BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); + BeanDefinitionBuilder beanDefinitionBuilder = + builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); - assertThat(beanDefinitionBuilder, is(notNullValue())); + assertThat(beanDefinitionBuilder).isNotNull(); AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); - assertThat(beanDefinition, is(notNullValue())); - assertThat(beanDefinition.getBeanClass(), is(equalTo(Object.class))); - assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues() - .getArgumentValue(0, RuntimeBeanReference.class).getValue()), - containsString(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME)); + assertThat(beanDefinition).isNotNull(); + assertThat(beanDefinition.getBeanClass()).isEqualTo(Object.class); + + ConstructorArgumentValues.ValueHolder constructorArgumentValue = + beanDefinition.getConstructorArgumentValues().getArgumentValue(0, RuntimeBeanReference.class); + + assertThat(constructorArgumentValue).isNotNull(); + assertThat(((RuntimeBeanReference) constructorArgumentValue.getValue()).getBeanName()).isEqualTo("gemfireCache"); + assertThat(beanDefinition.getPropertyValues().getPropertyValue("pool")).isNull(); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache")); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool")); - verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface(); } @Test @@ -96,11 +90,10 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration"); when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn("TestCache"); - when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(" "); - when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class); + when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(" "); - ServerBasedExecutionBeanDefinitionBuilder builder = - new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { + ServerBasedFunctionExecutionBeanDefinitionBuilder builder = + new ServerBasedFunctionExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { @Override protected Class getGemfireFunctionOperationsClass() { @@ -108,20 +101,25 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { } }; - BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); + BeanDefinitionBuilder beanDefinitionBuilder = + builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); - assertThat(beanDefinitionBuilder, is(notNullValue())); + assertThat(beanDefinitionBuilder).isNotNull(); AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); - assertThat(beanDefinition, is(notNullValue())); - assertThat(beanDefinition.getBeanClass(), is(equalTo(Object.class))); - assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues() - .getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestCache")); + assertThat(beanDefinition).isNotNull(); + assertThat(beanDefinition.getBeanClass()).isEqualTo(Object.class); + + ConstructorArgumentValues.ValueHolder constructorArgumentValue = + beanDefinition.getConstructorArgumentValues().getArgumentValue(0, RuntimeBeanReference.class); + + assertThat(constructorArgumentValue).isNotNull(); + assertThat(((RuntimeBeanReference) constructorArgumentValue.getValue()).getBeanName()).isEqualTo("TestCache"); + assertThat(beanDefinition.getPropertyValues().getPropertyValue("pool")).isNull(); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache")); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool")); - verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface(); } @Test @@ -133,10 +131,9 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn(null); when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn("TestPool"); - when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class); - ServerBasedExecutionBeanDefinitionBuilder builder = - new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { + ServerBasedFunctionExecutionBeanDefinitionBuilder builder = + new ServerBasedFunctionExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { @Override protected Class getGemfireFunctionOperationsClass() { @@ -144,20 +141,29 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { } }; - BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); + BeanDefinitionBuilder beanDefinitionBuilder = + builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); - assertThat(beanDefinitionBuilder, is(notNullValue())); + assertThat(beanDefinitionBuilder).isNotNull(); AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); - assertThat(beanDefinition, is(notNullValue())); - assertThat(beanDefinition.getBeanClass(), is(equalTo(Object.class))); - assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues() - .getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestPool")); + assertThat(beanDefinition).isNotNull(); + assertThat(beanDefinition.getBeanClass()).isEqualTo(Object.class); + + ConstructorArgumentValues.ValueHolder constructorArgumentValue = + beanDefinition.getConstructorArgumentValues().getArgumentValue(0, RuntimeBeanReference.class); + + assertThat(constructorArgumentValue).isNotNull(); + assertThat(((RuntimeBeanReference) constructorArgumentValue.getValue()).getBeanName()).isEqualTo("gemfireCache"); + + PropertyValue propertyValue = beanDefinition.getPropertyValues().getPropertyValue("pool"); + + assertThat(propertyValue).isNotNull(); + assertThat(((RuntimeBeanReference) propertyValue.getValue()).getBeanName()).isEqualTo("TestPool"); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache")); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool")); - verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface(); } @Test @@ -169,10 +175,9 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn("TestCache"); when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn("TestPool"); - when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class); - ServerBasedExecutionBeanDefinitionBuilder builder = - new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { + ServerBasedFunctionExecutionBeanDefinitionBuilder builder = + new ServerBasedFunctionExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) { @Override protected Class getGemfireFunctionOperationsClass() { @@ -180,15 +185,29 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest { } }; - expectedException.expect(IllegalStateException.class); - expectedException.expectCause(is(nullValue(Throwable.class))); - expectedException.expectMessage(is(equalTo("Invalid configuration for interface [java.lang.Object];" - + " cannot specify both 'pool' and 'cache'"))); - builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); + BeanDefinitionBuilder beanDefinitionBuilder = + builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null); + + assertThat(beanDefinitionBuilder).isNotNull(); + + AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition(); + + assertThat(beanDefinition).isNotNull(); + assertThat(beanDefinition.getBeanClass()).isEqualTo(Object.class); + + ConstructorArgumentValues.ValueHolder constructorArgumentValue = + beanDefinition.getConstructorArgumentValues().getArgumentValue(0, RuntimeBeanReference.class); + + assertThat(constructorArgumentValue).isNotNull(); + assertThat(((RuntimeBeanReference) constructorArgumentValue.getValue()).getBeanName()).isEqualTo("TestCache"); + + PropertyValue propertyValue = beanDefinition.getPropertyValues().getPropertyValue("pool"); + + assertThat(propertyValue).isNotNull(); + assertThat(((RuntimeBeanReference) propertyValue.getValue()).getBeanName()).isEqualTo("TestPool"); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache")); verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool")); - verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface(); } } diff --git a/src/test/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBeanTests.java b/src/test/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBeanUnitTests.java similarity index 51% rename from src/test/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBeanTests.java rename to src/test/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBeanUnitTests.java index ac77dd8c..de768e01 100644 --- a/src/test/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBeanTests.java +++ b/src/test/java/org/springframework/data/gemfire/function/execution/GemfireFunctionProxyFactoryBeanUnitTests.java @@ -1,26 +1,20 @@ /* * Copyright 2002-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.execution; -/** - * @author David Turanski - * - */ - - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,81 +28,92 @@ import org.aopalliance.intercept.MethodInvocation; import org.junit.Before; import org.junit.Test; import org.springframework.data.gemfire.function.annotation.FunctionId; - -/** - * - * @author David Turanski - * - */ -public class GemfireFunctionProxyFactoryBeanTests { - +/** + * Unit tests for {@link GemfireFunctionProxyFactoryBean}. + * + * @author David Turanski + * @author John Blum + * @see org.junit.Test + * @see org.mockito.Mockito + * @see org.aopalliance.intercept.MethodInvocation + * @see org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean + */ +public class GemfireFunctionProxyFactoryBeanUnitTests { + private GemfireFunctionOperations functionOperations; @Before public void setUp() { - functionOperations = mock(GemfireFunctionOperations.class); + this.functionOperations = mock(GemfireFunctionOperations.class); } @Test - public void testInvokeAndExtractWithAnnotatedFunctionId() throws Throwable { - - - GemfireFunctionProxyFactoryBean proxy = new GemfireFunctionProxyFactoryBean(IFoo.class,functionOperations); - - MethodInvocation invocation = new TestInvocation(IFoo.class).withMethodNameAndArgTypes("oneArg",String.class); - - int results = 1; - - when(functionOperations.executeAndExtract("oneArg",invocation.getArguments())).thenReturn(results); + public void invoke() throws Throwable { + + MethodInvocation invocation = new TestMethodInvocation(IFoo.class) + .withMethodNameAndArgTypes("collections",List.class); + + when(this.functionOperations.executeAndExtract("collections",invocation.getArguments())) + .thenReturn(Arrays.asList(1, 2, 3)); + + GemfireFunctionProxyFactoryBean proxy = new GemfireFunctionProxyFactoryBean(IFoo.class, this.functionOperations); + Object result = proxy.invoke(invocation); - verify(functionOperations).executeAndExtract("oneArg",invocation.getArguments()); - assertTrue(result.getClass().getName(), result instanceof Integer); - assertEquals(1,result); + + assertThat(result).isInstanceOf(List.class); + assertThat((List) result).hasSize(3); + + verify(this.functionOperations, times(1)) + .executeAndExtract("collections",invocation.getArguments()); } - - - @SuppressWarnings({ "rawtypes" }) + @Test - public void testInvoke() throws Throwable { - - - GemfireFunctionProxyFactoryBean proxy = new GemfireFunctionProxyFactoryBean(IFoo.class, functionOperations); - - MethodInvocation invocation = new TestInvocation(IFoo.class).withMethodNameAndArgTypes("collections",List.class); - - List results = Arrays.asList(new Integer[]{1,2,3}); - - when(functionOperations.executeAndExtract("collections",invocation.getArguments())).thenReturn(results); + public void invokeAndExtractWithAnnotatedFunctionId() throws Throwable { + + MethodInvocation invocation = new TestMethodInvocation(IFoo.class) + .withMethodNameAndArgTypes("oneArg", String.class); + + when(this.functionOperations.executeAndExtract("oneArg",invocation.getArguments())).thenReturn(1); + + GemfireFunctionProxyFactoryBean proxy = new GemfireFunctionProxyFactoryBean(IFoo.class, this.functionOperations); + Object result = proxy.invoke(invocation); - verify(functionOperations).executeAndExtract("collections",invocation.getArguments()); ; - assertTrue(result instanceof List); - assertEquals(3,((List)result).size()); + + assertThat(result).describedAs(result.getClass().getName()).isInstanceOf(Integer.class); + assertThat(result).isEqualTo(1); + + verify(this.functionOperations, times(1)) + .executeAndExtract("oneArg", invocation.getArguments()); } - - - - static class TestInvocation implements MethodInvocation { - + + @SuppressWarnings("unused") + private static class TestMethodInvocation implements MethodInvocation { + + private Class type; + private Class[] argTypes; - private Class clazz; - private String methodName; + private Object[] arguments; - public TestInvocation(Class clazz) { - this.clazz = clazz; + private String methodName; + + public TestMethodInvocation(Class type) { + this.type = type; } - - public TestInvocation withArguments(Object ...arguments){ + + public TestMethodInvocation withArguments(Object ...arguments){ + this.arguments = arguments; + return this; } - - - - public TestInvocation withMethodNameAndArgTypes(String methodName,Class... argTypes) { + + public TestMethodInvocation withMethodNameAndArgTypes(String methodName,Class... argTypes) { + this.methodName = methodName; this.argTypes = argTypes; + return this; } @@ -117,7 +122,6 @@ public class GemfireFunctionProxyFactoryBeanTests { */ @Override public Object[] getArguments() { - // TODO Auto-generated method stub return this.arguments; } @@ -126,7 +130,6 @@ public class GemfireFunctionProxyFactoryBeanTests { */ @Override public Object proceed() throws Throwable { - // TODO Auto-generated method stub return null; } @@ -135,7 +138,6 @@ public class GemfireFunctionProxyFactoryBeanTests { */ @Override public Object getThis() { - // TODO Auto-generated method stub return null; } @@ -144,7 +146,6 @@ public class GemfireFunctionProxyFactoryBeanTests { */ @Override public AccessibleObject getStaticPart() { - // TODO Auto-generated method stub return null; } @@ -153,35 +154,27 @@ public class GemfireFunctionProxyFactoryBeanTests { */ @Override public Method getMethod() { - Method method = null; + try { - method = clazz.getMethod(methodName, argTypes); - } catch (SecurityException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (NoSuchMethodException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + return this.type.getMethod(methodName, argTypes); + } + catch (NoSuchMethodException | SecurityException cause) { + return null; } - return method; } - } - + + @SuppressWarnings("unused") public interface IFoo { @FunctionId("oneArg") - public abstract Integer oneArg(String key); + Integer oneArg(String key); - public abstract Integer twoArg(String akey, String bkey); + Integer twoArg(String akey, String bkey); - public abstract List collections(List args); + List collections(List args); - public abstract Map getMapWithNoArgs(); + Map getMapWithNoArgs(); } - - } - -