SGF-749 - Expose SDG's Function annotation configuration as part of the public API for extension purposes.

This commit is contained in:
John Blum
2018-05-23 13:37:24 -07:00
parent fe9a2e477f
commit af37012d33
8 changed files with 142 additions and 105 deletions

View File

@@ -26,8 +26,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.ResourceLoader;
@@ -50,7 +50,7 @@ import org.springframework.data.gemfire.function.annotation.OnServers;
* @author John Blum
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfiguration
*/
abstract class AbstractFunctionExecutionConfigurationSource implements FunctionExecutionConfigurationSource {
public abstract class AbstractFunctionExecutionConfigurationSource implements FunctionExecutionConfigurationSource {
private static Set<Class<? extends Annotation>> functionExecutionAnnotationTypes;
@@ -67,15 +67,15 @@ abstract class AbstractFunctionExecutionConfigurationSource implements FunctionE
functionExecutionAnnotationTypes = Collections.unmodifiableSet(annotationTypes);
}
static Set<Class<? extends Annotation>> getFunctionExecutionAnnotationTypes() {
public static Set<Class<? extends Annotation>> getFunctionExecutionAnnotationTypes() {
return functionExecutionAnnotationTypes;
}
static Set<String> getFunctionExecutionAnnotationTypeNames() {
public static Set<String> getFunctionExecutionAnnotationTypeNames() {
return getFunctionExecutionAnnotationTypes().stream().map(Class::getName).collect(Collectors.toSet());
}
protected Log logger = LogFactory.getLog(getClass());
protected Logger logger = LoggerFactory.getLogger(getClass());
public Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader) {

View File

@@ -12,6 +12,8 @@
*/
package org.springframework.data.gemfire.function.config;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
@@ -27,6 +29,7 @@ import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.gemfire.util.ArrayUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -36,10 +39,11 @@ import org.springframework.util.ClassUtils;
* @author David Turanski
*
*/
class AnnotationFunctionExecutionConfigurationSource extends AbstractFunctionExecutionConfigurationSource {
public class AnnotationFunctionExecutionConfigurationSource extends AbstractFunctionExecutionConfigurationSource {
private static final String BASE_PACKAGES = "basePackages";
private static final String BASE_PACKAGE_CLASSES = "basePackageClasses";
private static final String VALUE = "value";
private final AnnotationMetadata metadata;
private final AnnotationAttributes attributes;
@@ -51,13 +55,14 @@ class AnnotationFunctionExecutionConfigurationSource extends AbstractFunctionExe
*
* @param metadata must not be {@literal null}.
*/
AnnotationFunctionExecutionConfigurationSource(AnnotationMetadata metadata) {
public AnnotationFunctionExecutionConfigurationSource(AnnotationMetadata metadata) {
Assert.notNull(metadata);
Assert.notNull(metadata, "AnnotationMetadata must not be null");
this.attributes = AnnotationAttributes.fromMap(
metadata.getAnnotationAttributes(EnableGemfireFunctionExecutions.class.getName()));
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(EnableGemfireFunctionExecutions.class.getName()));
this.metadata = metadata;
}
@@ -67,7 +72,6 @@ class AnnotationFunctionExecutionConfigurationSource extends AbstractFunctionExe
*/
@Override
public Object getSource() {
// TODO Auto-generated method stub
return this.metadata;
}
@@ -76,27 +80,42 @@ class AnnotationFunctionExecutionConfigurationSource extends AbstractFunctionExe
*/
@Override
public Iterable<String> getBasePackages() {
String[] value = attributes.getStringArray("value");
String[] basePackages = attributes.getStringArray(BASE_PACKAGES);
Class<?>[] basePackageClasses = attributes.getClassArray(BASE_PACKAGE_CLASSES);
String[] value = this.attributes.getStringArray(VALUE);
String[] basePackages = this.attributes.getStringArray(BASE_PACKAGES);
Class<?>[] basePackageClasses = this.attributes.getClassArray(BASE_PACKAGE_CLASSES);
// Default configuration - return package of annotated class
if (value.length == 0 && basePackages.length == 0 && basePackageClasses.length == 0) {
String className = metadata.getClassName();
if (areAllEmpty(value, basePackages, basePackageClasses)) {
String className = this.metadata.getClassName();
return Collections.singleton(className.substring(0, className.lastIndexOf('.')));
}
Set<String> packages = new HashSet<String>();
Set<String> packages = new HashSet<>();
packages.addAll(Arrays.asList(value));
packages.addAll(Arrays.asList(basePackages));
for (Class<?> typeName : basePackageClasses) {
packages.add(ClassUtils.getPackageName(typeName));
}
Arrays.stream(nullSafeArray(basePackageClasses, Class.class))
.map(ClassUtils::getPackageName)
.forEach(packages::add);
return packages;
}
private boolean areAllEmpty(Object[]... arrays) {
for (Object[] array : arrays) {
if (!ArrayUtils.isEmpty(array)) {
return false;
}
}
return true;
}
@Override
public Iterable<TypeFilter> getIncludeFilters() {

View File

@@ -30,18 +30,26 @@ import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.function.annotation.OnMember;
import org.springframework.data.gemfire.function.annotation.OnMembers;
import org.springframework.data.gemfire.function.annotation.OnRegion;
import org.springframework.data.gemfire.function.annotation.OnServer;
import org.springframework.data.gemfire.function.annotation.OnServers;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* {@link ImportBeanDefinitionRegistrar} for {code} @EnableGemfireFunctionExecutions {code}
* Scans for interfaces annotated with one of {code} @OnRegion, @OnServer, @OnServers, @OnMember, @OnMembers {code}
* {@link ImportBeanDefinitionRegistrar} for {@link EnableGemfireFunctionExecutions}, which scans for interfaces
* annotated with one of {@link OnRegion}, {@link OnServer}, {@link OnServers}, {@link OnMember}, {@link OnMembers}.
*
* @author David Turanski
* @author John Blum
* @see org.springframework.beans.factory.support.BeanDefinitionRegistry
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
* @see org.springframework.context.annotation.ScannedGenericBeanDefinition
*/
class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/*
* (non-Javadoc)
@@ -52,20 +60,32 @@ class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRe
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
AbstractFunctionExecutionConfigurationSource configurationSource =
new AnnotationFunctionExecutionConfigurationSource(annotationMetadata);
newAnnotationBasedFunctionExecutionConfigurationSource(annotationMetadata);
registerBeanDefinitions(configurationSource, registry);
}
void registerBeanDefinitions(Element element, ParserContext parserContext) {
protected AbstractFunctionExecutionConfigurationSource newAnnotationBasedFunctionExecutionConfigurationSource(
AnnotationMetadata annotationMetadata) {
return new AnnotationFunctionExecutionConfigurationSource(annotationMetadata);
}
protected void registerBeanDefinitions(Element element, ParserContext parserContext) {
AbstractFunctionExecutionConfigurationSource configurationSource =
new XmlFunctionExecutionConfigurationSource(element, parserContext);
newXmlBasedFunctionExecutionConfigurationSource(element, parserContext);
registerBeanDefinitions(configurationSource, parserContext.getRegistry());
}
protected AbstractFunctionExecutionConfigurationSource newXmlBasedFunctionExecutionConfigurationSource(
Element element, ParserContext parserContext) {
return new XmlFunctionExecutionConfigurationSource(element, parserContext);
}
/**
* Registers bean definitions from any {@link FunctionExecutionConfigurationSource}.
*/

View File

@@ -21,20 +21,13 @@ import java.lang.annotation.Annotation;
import org.springframework.core.type.filter.TypeFilter;
/**
<<<<<<< Updated upstream
* Interface for function execution configuration sources (e.g., annotation or XML configuration) to configure
* classpath scanning of annotated interfaces to implement proxies that invoke Gemfire functions
*
* @author David Turanski
=======
* Interface for Function Execution configuration sources (e.g. {@link Annotation} or XML configuration)
* to configure classpath scanning of annotated interfaces to implement proxies that invoke Functions.
>>>>>>> Stashed changes
*
* @author David Turanski
* @author John Blum
*/
interface FunctionExecutionConfigurationSource {
public interface FunctionExecutionConfigurationSource {
/**
* Returns the base packages the repository interfaces shall be found under.

View File

@@ -14,37 +14,39 @@ package org.springframework.data.gemfire.function.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.data.gemfire.function.annotation.OnMember;
import org.springframework.data.gemfire.function.annotation.OnMembers;
import org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean;
import org.springframework.util.StringUtils;
/**
* A base class for OnMember and OnMembers function execution bean definition builders.
* Base class for {@link OnMember} and {@link OnMembers} Function execution
* {@link BeanDefinitionBuilder BeanDefinitionBuilders}.
*
* @author David Turanski
*
* @author John Blum
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder
*/
abstract class MemberBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
abstract class MemberBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
public MemberBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
MemberBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (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(getGemfireOperationsClass());
BeanDefinitionBuilder functionTemplateBuilder =
BeanDefinitionBuilder.genericBeanDefinition(getGemfireOperationsClass());
String groups = (String)configuration.getAttribute("groups");
if (StringUtils.hasText(groups)) {
functionTemplateBuilder.addConstructorArgValue(StringUtils.commaDelimitedListToStringArray(groups));
}
@@ -62,4 +64,5 @@ import org.springframework.util.StringUtils;
}
protected abstract Class<?> getGemfireOperationsClass();
}

View File

@@ -15,19 +15,22 @@ package org.springframework.data.gemfire.function.config;
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;
/**
* @author David Turanski
* Base class for {@link OnServer} and {@link OnServers} Function execution
* {@link BeanDefinitionBuilder BeanDefinitionBuilders}.
*
* @author David Turanski
* @author John Blum
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder
*/
abstract class ServerBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
ServerBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
@@ -38,18 +41,19 @@ abstract class ServerBasedExecutionBeanDefinitionBuilder extends AbstractFunctio
*/
@Override
protected BeanDefinitionBuilder getGemfireFunctionOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(
getGemfireFunctionOperationsClass());
String cache = (String) configuration.getAttribute("cache");
String pool = (String) configuration.getAttribute("pool");
BeanDefinitionBuilder functionTemplateBuilder =
BeanDefinitionBuilder.genericBeanDefinition(getGemfireFunctionOperationsClass());
Assert.state(!(StringUtils.hasText(cache) && StringUtils.hasText(pool)), String.format(
"invalid configuration for interface %s; cannot specify both 'pool' and 'cache'",
configuration.getFunctionExecutionInterface().getName()));
String cache = (String) this.configuration.getAttribute("cache");
String pool = (String) this.configuration.getAttribute("pool");
functionTemplateBuilder.addConstructorArgReference(StringUtils.hasText(pool) ? pool
: (StringUtils.hasText(cache) ? cache : GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
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));
return functionTemplateBuilder;
}

View File

@@ -29,7 +29,7 @@ import org.w3c.dom.Element;
* @author David Turanski
*
*/
class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionConfigurationSource {
public class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionConfigurationSource {
private static final String BASE_PACKAGE = "base-package";
@@ -40,7 +40,7 @@ class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionC
private final ParserContext parserContext;
XmlFunctionExecutionConfigurationSource(Element element, ParserContext parserContext) {
public XmlFunctionExecutionConfigurationSource(Element element, ParserContext parserContext) {
Assert.notNull(element, "Element must not be null");
Assert.notNull(parserContext, "ParserContext must not be null");

View File

@@ -31,8 +31,6 @@ import static org.mockito.Mockito.when;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -56,22 +54,22 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest {
@Test
@SuppressWarnings("unchecked")
public void getGemfireFunctionOperationsBeanDefinitionBuilder() {
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn(null);
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(" ");
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
return Object.class;
}
});
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class);
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
ServerBasedExecutionBeanDefinitionBuilder builder =
new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override
protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
@@ -80,7 +78,7 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest {
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
assertThat(beanDefinition, is(notNullValue()));
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
.getArgumentValue(0, RuntimeBeanReference.class).getValue()),
containsString(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
@@ -93,22 +91,22 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest {
@Test
@SuppressWarnings("unchecked")
public void getGemfireFunctionOperationsBeanDefinitionBuilderWithCache() {
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn("TestCache");
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(" ");
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
return Object.class;
}
});
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class);
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
ServerBasedExecutionBeanDefinitionBuilder builder =
new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override
protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
@@ -117,7 +115,7 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest {
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
assertThat(beanDefinition, is(notNullValue()));
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
.getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestCache"));
@@ -129,22 +127,22 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest {
@Test
@SuppressWarnings("unchecked")
public void getGemfireFunctionOperationsBeanDefinitionBuilderWithPool() {
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn(null);
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn("TestPool");
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
return Object.class;
}
});
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class);
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
ServerBasedExecutionBeanDefinitionBuilder builder =
new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override
protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
@@ -153,7 +151,7 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest {
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
assertThat(beanDefinition, is(notNullValue()));
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
.getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestPool"));
@@ -165,32 +163,32 @@ public class ServerBasedExecutionBeanDefinitionBuilderTest {
@Test
@SuppressWarnings("unchecked")
public void getGemfireFunctionOperationsBeanDefinitionBuilderWithCacheAndPool() {
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn("TestCache");
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn("TestPool");
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
return Object.class;
}
});
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(invocation -> Object.class);
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
ServerBasedExecutionBeanDefinitionBuilder builder =
new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override
protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
expectedException.expect(IllegalStateException.class);
expectedException.expectCause(is(nullValue(Throwable.class)));
expectedException.expectMessage(is(equalTo("invalid configuration for interface java.lang.Object;"
expectedException.expectMessage(is(equalTo("Invalid configuration for interface [java.lang.Object];"
+ " cannot specify both 'pool' and 'cache'")));
builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
}
}