SGF-423 - Handle improper ClassCastException thrown from SDG's Function Execution interface and annotation-based support when a GemFire Function throws an Exception.

Additional refactoring and added serveral unit tests.
(cherry picked from commit a806f1540e6fc995410671f34382d14389ace90a)

Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2015-08-07 01:36:59 -07:00
parent 677d46c1df
commit cd4a2497b7
16 changed files with 1005 additions and 152 deletions

View File

@@ -71,7 +71,9 @@ abstract class AbstractFunctionExecutionConfigurationSource implements FunctionE
}
public Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader) {
ClassPathScanningCandidateComponentProvider scanner = new FunctionExecutionComponentProvider(getIncludeFilters(),functionExecutionAnnotationTypes);
ClassPathScanningCandidateComponentProvider scanner = new FunctionExecutionComponentProvider(
getIncludeFilters(), getFunctionExecutionAnnotationTypes());
scanner.setResourceLoader(loader);
for (TypeFilter filter : getExcludeFilters()) {
@@ -84,9 +86,11 @@ abstract class AbstractFunctionExecutionConfigurationSource implements FunctionE
if (logger.isDebugEnabled()) {
logger.debug("scanning package " + basePackage);
}
Collection<BeanDefinition> components = scanner.findCandidateComponents(basePackage);
for (BeanDefinition definition : components) {
result.add((ScannedGenericBeanDefinition)definition);
Collection<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
for (BeanDefinition beanDefinition : candidateComponents) {
result.add((ScannedGenericBeanDefinition) beanDefinition);
}
}

View File

@@ -12,8 +12,6 @@
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
@@ -21,7 +19,6 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -52,7 +49,9 @@ class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRe
void registerBeanDefinitions(AbstractFunctionExecutionConfigurationSource functionExecutionConfigurationSource,
BeanDefinitionRegistry registry) {
for (ScannedGenericBeanDefinition beanDefinition : functionExecutionConfigurationSource.getCandidates(new DefaultResourceLoader())) {
for (ScannedGenericBeanDefinition beanDefinition : functionExecutionConfigurationSource.getCandidates(
new DefaultResourceLoader())) {
String functionExecutionAnnotation = getFunctionExecutionAnnotation(beanDefinition,
AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypeNames());

View File

@@ -31,6 +31,12 @@ class FunctionExecutionConfiguration {
private final String annotationType;
/* constructor for testing purposes only! */
FunctionExecutionConfiguration() {
this.annotationType = null;
this.attributes = null;
}
FunctionExecutionConfiguration(ScannedGenericBeanDefinition beanDefinition, String annotationType) {
try {
this.annotationType = annotationType;

View File

@@ -44,7 +44,7 @@ abstract class ServerBasedExecutionBeanDefinitionBuilder extends AbstractFunctio
String cache = (String) configuration.getAttribute("cache");
String pool = (String) configuration.getAttribute("pool");
Assert.state(StringUtils.hasText(cache) && !(StringUtils.hasText(pool)), String.format(
Assert.state(!(StringUtils.hasText(cache) && StringUtils.hasText(pool)), String.format(
"invalid configuration for interface %s; cannot specify both 'pool' and 'cache'",
configuration.getFunctionExecutionInterface().getName()));

View File

@@ -29,22 +29,27 @@ import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.cache.execute.ResultCollector;
/**
* Base class for * Creating a GemFire {@link Execution} using {@link FunctionService}
* Protected setters support method chaining
* @author David Turanski
* Base class for * Creating a GemFire {@link Execution} using {@link FunctionService}. Protected setters support
* method chaining.
*
* @author David Turanski
* @author John Blum
*/
abstract class AbstractFunctionExecution {
private final static String NO_RESULT_MESSAGE = "Cannot return any result as the Function#hasResult() is false";
private long timeout;
private Function function;
protected final Log logger = LogFactory.getLog(this.getClass());
private volatile ResultCollector<?, ?> resultCollector;
private Object[] args;
private Function function;
private volatile ResultCollector<?, ?> resultCollector;
private String functionId;
private long timeout;
public AbstractFunctionExecution(Function function, Object... args) {
Assert.notNull(function, "function cannot be null");
@@ -62,22 +67,22 @@ abstract class AbstractFunctionExecution {
AbstractFunctionExecution() {
}
ResultCollector<?, ?> getCollector() {
return resultCollector;
}
Object[] getArgs() {
return args;
}
String getFunctionId() {
return functionId;
ResultCollector<?, ?> getCollector() {
return resultCollector;
}
Function getFunction() {
return function;
}
String getFunctionId() {
return functionId;
}
long getTimeout() {
return timeout;
}
@@ -88,33 +93,31 @@ abstract class AbstractFunctionExecution {
@SuppressWarnings("unchecked")
<T> Iterable<T> execute(Boolean returnResult) {
Execution execution = this.getExecution();
if (getKeys() != null) {
execution = execution.withFilter(getKeys());
}
if (getCollector() != null) {
execution = execution.withCollector(getCollector());
}
ResultCollector<?, ?> resultCollector = null;
Execution execution = getExecution();
execution = execution.withArgs(getArgs());
execution = (getCollector() == null ? execution : execution.withCollector(getCollector()));
execution = (getKeys() == null ? execution : execution.withFilter(getKeys()));
ResultCollector<?, ?> resultCollector;
if (isRegisteredFunction()) {
resultCollector = (ResultCollector<?, ?>) execution.execute(functionId);
} else {
resultCollector = (ResultCollector<?, ?>) execution.execute(function);
resultCollector = execution.execute(functionId);
}
else {
resultCollector = execution.execute(function);
if (!function.hasResult()) {
return (Iterable<T>) null;
return null;
}
}
if (!returnResult) {
return (Iterable<T>) null;
return null;
}
if (logger.isDebugEnabled()) {
logger.debug("using ResultsCollector:" + resultCollector.getClass().getName());
logger.debug("using ResultsCollector " + resultCollector.getClass().getName());
}
Iterable<T> results = null;
@@ -123,41 +126,53 @@ abstract class AbstractFunctionExecution {
if (this.timeout > 0) {
try {
results = (Iterable<T>) resultCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
} catch (FunctionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
}
catch (FunctionException e) {
throw new RuntimeException(e);
}
} else {
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
else {
results = (Iterable<T>) resultCollector.getResult();
}
return replaceSingletonNullCollectionWithEmptyList(results);
} catch (FunctionException e) {
//TODO: Come up with a better way to determine that the function should not return a result;
}
catch (FunctionException e) {
//TODO Come up with a better way to determine that the function should not return a result;
if (!e.getMessage().equals(NO_RESULT_MESSAGE)) {
throw e;
}
}
return results;
}
@SuppressWarnings("unchecked")
<T> T executeAndExtract() {
Iterable<T> results = this.execute();
Iterable<T> results = execute();
if (results == null || !results.iterator().hasNext()) {
return null;
}
return results.iterator().next();
Object result = results.iterator().next();
if (result instanceof Throwable) {
throw new FunctionException(String.format("Execution of Function %1$s failed",
(function != null ? function.getClass().getName() : String.format("with ID '%1$s'", functionId))),
(Throwable) result);
}
return (T) result;
}
protected abstract Execution getExecution();
protected AbstractFunctionExecution setFunctionId(String functionId) {
this.functionId = functionId;
protected AbstractFunctionExecution setArgs(Object... args) {
this.args = args;
return this;
}
@@ -166,17 +181,8 @@ abstract class AbstractFunctionExecution {
return this;
}
protected AbstractFunctionExecution setArgs(Object... args) {
this.args = args;
return this;
}
protected Set<?> getKeys() {
return null;
}
protected AbstractFunctionExecution setTimeout(long timeout) {
this.timeout = timeout;
protected AbstractFunctionExecution setFunctionId(String functionId) {
this.functionId = functionId;
return this;
}
@@ -185,29 +191,33 @@ abstract class AbstractFunctionExecution {
return this;
}
/**
* @return
*/
protected AbstractFunctionExecution setTimeout(long timeout) {
this.timeout = timeout;
return this;
}
protected Set<?> getKeys() {
return null;
}
private boolean isRegisteredFunction() {
return function == null;
}
private <T> Iterable<T> replaceSingletonNullCollectionWithEmptyList(Iterable<T> results) {
if (results == null) {
return results;
}
Iterator<T> it = results.iterator();
if (results != null) {
Iterator<T> it = results.iterator();
if (!it.hasNext()) {
return results;
}
if (!it.hasNext()) {
return results;
}
if (it.next() == null && !it.hasNext()) {
return new ArrayList<T>();
if (it.next() == null && !it.hasNext()) {
return new ArrayList<T>();
}
}
return results;
}
}
}

View File

@@ -15,100 +15,79 @@ package org.springframework.data.gemfire.function.execution;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.ResultCollector;
/**
*
* The base class for Gemfire function templates used to invoke Gemfire functions
* @author David Turanski
* The base class for GemFire FunctionTemplates used to invoke GemFire Functions.
*
* @author David Turanski
* @author John Blum
* @see com.gemstone.gemfire.cache.execute.Function
* @see com.gemstone.gemfire.cache.execute.ResultCollector
*/
abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
protected Log log = LogFactory.getLog(this.getClass());
protected long timeout;
protected volatile ResultCollector<?, ?> resultCollector;
@Override
public <T> Iterable<T> execute(Function function, Object... args) {
AbstractFunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunction(function);
return execute(functionExecution);
return execute(getFunctionExecution().setArgs(args).setFunction(function));
}
@Override
public <T> T executeAndExtract(Function function, Object... args) {
AbstractFunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunction(function);
return this.<T> executeAndExtract(functionExecution);
return executeAndExtract(getFunctionExecution().setArgs(args).setFunction(function));
}
@Override
public <T> Iterable<T> execute(String functionId, Object... args) {
AbstractFunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId);
return execute(functionExecution);
return execute(getFunctionExecution().setArgs(args).setFunctionId(functionId));
}
@Override
public void executeWithNoResult(String functionId, Object... args) {
AbstractFunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId);
execute(functionExecution,false);
}
@Override
public <T> T executeAndExtract(String functionId, Object... args) {
AbstractFunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId);
return this.<T>executeAndExtract(functionExecution);
return executeAndExtract(getFunctionExecution().setArgs(args).setFunctionId(functionId));
}
@Override
public void executeWithNoResult(String functionId, Object... args) {
execute(getFunctionExecution().setArgs(args).setFunctionId(functionId), false);
}
@Override
public <T> T execute(GemfireFunctionCallback<T> callback) {
Execution execution = getFunctionExecution().getExecution();
return callback.doInGemfire(execution);
return callback.doInGemfire(getFunctionExecution().getExecution());
}
protected <T> Iterable<T> execute(AbstractFunctionExecution execution) {
execution.setTimeout(timeout)
.setResultCollector(resultCollector);
return execution.execute();
return execution.setTimeout(timeout).setResultCollector(resultCollector).execute();
}
protected <T> Iterable<T> execute(AbstractFunctionExecution execution, boolean returnResult) {
execution.setTimeout(timeout)
.setResultCollector(resultCollector);
return execution.execute(returnResult);
return execution.setTimeout(timeout).setResultCollector(resultCollector).execute(returnResult);
}
protected <T> T executeAndExtract(AbstractFunctionExecution execution) {
execution.setTimeout(timeout)
.setResultCollector(resultCollector);
return execution.<T>executeAndExtract();
return execution.setTimeout(timeout).setResultCollector(resultCollector).executeAndExtract();
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public void setResultCollector(ResultCollector<?,?> resultCollector) {
this.resultCollector = resultCollector;
}
public ResultCollector<?,?> getResultCollector() {
return this.resultCollector;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
protected abstract AbstractFunctionExecution getFunctionExecution();
}

View File

@@ -75,9 +75,8 @@ public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, Met
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (AopUtils.isToStringMethod(invocation.getMethod())) {
return "Gemfire function proxy for service interface [" + this.functionExecutionInterface + "]";
return "GemFire Function Proxy for service interface [" + this.functionExecutionInterface + "]";
}
if (logger.isDebugEnabled()) {

View File

@@ -18,30 +18,26 @@ import com.gemstone.gemfire.cache.client.Pool;
/**
* @author David Turanski
*
* @author John Blum
*/
public class GemfireOnServerFunctionTemplate extends AbstractFunctionTemplate {
private final RegionService cache;
private final Pool pool;
public GemfireOnServerFunctionTemplate (RegionService cache) {
private final Pool pool;
private final RegionService cache;
public GemfireOnServerFunctionTemplate(RegionService cache) {
this.cache = cache;
this.pool = null;
}
public GemfireOnServerFunctionTemplate (Pool pool) {
this.pool = pool;
public GemfireOnServerFunctionTemplate(Pool pool) {
this.cache = null;
this.pool = pool;
}
@Override
protected AbstractFunctionExecution getFunctionExecution() {
if (this.pool == null) {
return new ServerFunctionExecution(this.cache);
}
return new PoolServerFunctionExecution(this.pool);
return (pool != null ? new PoolServerFunctionExecution(this.pool) : new ServerFunctionExecution(this.cache));
}
}

View File

@@ -24,20 +24,17 @@ import com.gemstone.gemfire.cache.execute.FunctionService;
*
*/
class ServerFunctionExecution extends AbstractFunctionExecution {
private RegionService regionService;
private final RegionService regionService;
public ServerFunctionExecution(RegionService regionService) {
super();
Assert.notNull(regionService,"regionService cannot be null");
Assert.notNull(regionService, "RegionService must not be null");
this.regionService = regionService;
}
@Override
protected Execution getExecution() {
return FunctionService.onServer(this.regionService);
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.function;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.isA;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.gemfire.fork.ServerProcess;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.data.gemfire.function.sample.ExceptionThrowingFunctionExecution;
import org.springframework.data.gemfire.process.ProcessExecutor;
import org.springframework.data.gemfire.process.ProcessWrapper;
import org.springframework.data.gemfire.test.support.FileSystemUtils;
import org.springframework.data.gemfire.test.support.ThreadUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.execute.FunctionAdapter;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.FunctionException;
/**
* The ExceptionThrowingFunctionExecutionIntegrationTest class is a test suite of test cases testing the invocation
* of a GemFire Function using Spring Data GemFire Function Execution Annotation support when that Function throws
* an Exception.
*
* @author John Blum
* @see org.junit.Rule
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.data.gemfire.fork.ServerProcess
* @see org.springframework.data.gemfire.function.annotation.GemfireFunction
* @see org.springframework.data.gemfire.function.sample.ExceptionThrowingFunctionExecution
* @see org.springframework.data.gemfire.process.ProcessExecutor
* @see org.springframework.data.gemfire.process.ProcessWrapper
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @since 1.7.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@SuppressWarnings("unused")
public class ExceptionThrowingFunctionExecutionIntegrationTest {
private static ProcessWrapper serverProcess;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Autowired
private ExceptionThrowingFunctionExecution exceptionThrowingFunctionExecution;
@BeforeClass
public static void setup() throws IOException {
String serverName = ExceptionThrowingFunctionExecutionIntegrationTest.class.getSimpleName().concat("Server");
File serverWorkingDirectory = new File(FileSystemUtils.WORKING_DIRECTORY, serverName.toLowerCase());
Assert.isTrue(serverWorkingDirectory.isDirectory() || serverWorkingDirectory.mkdirs());
List<String> arguments = new ArrayList<String>();
arguments.add("-Dgemfire.name=" + serverName);
arguments.add(ExceptionThrowingFunctionExecutionIntegrationTest.class.getName().replaceAll("\\.",
File.separator)
.concat("-server-context.xml"));
serverProcess = ProcessExecutor.launch(serverWorkingDirectory, ServerProcess.class,
arguments.toArray(new String[arguments.size()]));
waitForServerStart(TimeUnit.SECONDS.toMillis(20));
System.out.println("GemFire Cache Server Process for ClientCache Indexing should be running...");
}
private static void waitForServerStart(final long milliseconds) {
ThreadUtils.timedWait(milliseconds, TimeUnit.MILLISECONDS.toMillis(500), new ThreadUtils.WaitCondition() {
private File serverPidControlFile = new File(serverProcess.getWorkingDirectory(),
ServerProcess.getServerProcessControlFilename());
@Override public boolean waiting() {
return !serverPidControlFile.isFile();
}
});
}
@AfterClass
public static void tearDown() {
serverProcess.shutdown();
if (Boolean.valueOf(System.getProperty("spring.gemfire.fork.clean", Boolean.TRUE.toString()))) {
org.springframework.util.FileSystemUtils.deleteRecursively(serverProcess.getWorkingDirectory());
}
}
@Test
public void exceptionThrowingFunctionExecutionRethrowsException() {
expectedException.expect(FunctionException.class);
expectedException.expectCause(isA(IllegalArgumentException.class));
expectedException.expectMessage(containsString("Execution of Function with ID 'exceptionThrowingFunction' failed"));
exceptionThrowingFunctionExecution.exceptionThrowingFunction();
}
public static class ExceptionThrowingFunction extends FunctionAdapter {
@Override
public String getId() {
return "exceptionThrowingFunction";
}
@Override
public void execute(final FunctionContext context) {
context.getResultSender().sendException(new IllegalArgumentException("TEST"));
}
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.function.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.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.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;
import org.springframework.data.gemfire.config.GemfireConstants;
/**
* The ServerBasedExecutionBeanDefinitionBuilderTest class is test suite of test cases testing the contract
* and functionality of the ServerBasedExecutionBeanDefinitionBuilder class.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder
* @since 1.7.0
*/
public class ServerBasedExecutionBeanDefinitionBuilderTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@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;
}
});
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
assertThat(beanDefinitionBuilder, is(notNullValue()));
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
assertThat(beanDefinition, is(notNullValue()));
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
.getArgumentValue(0, RuntimeBeanReference.class).getValue()),
containsString(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
}
@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;
}
});
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
assertThat(beanDefinitionBuilder, is(notNullValue()));
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
assertThat(beanDefinition, is(notNullValue()));
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
.getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestCache"));
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
}
@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;
}
});
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
@Override protected Class<?> getGemfireFunctionOperationsClass() {
return Object.class;
}
};
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
assertThat(beanDefinitionBuilder, is(notNullValue()));
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
assertThat(beanDefinition, is(notNullValue()));
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
.getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestPool"));
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
}
@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;
}
});
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;"
+ " 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();
}
}

View File

@@ -0,0 +1,199 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.isA;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionException;
import com.gemstone.gemfire.cache.execute.ResultCollector;
/**
* The AbstractFunctionExecutionTest class is a test suite of test cases testing the contract and functionality
* of the AbstractFunctionExecution class.
*
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.mockito.Mockito
* @see org.mockito.runners.MockitoJUnitRunner
* @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution
* @see com.gemstone.gemfire.cache.execute.Execution
* @since 1.7.0
*/
@RunWith(MockitoJUnitRunner.class)
public class AbstractFunctionExecutionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Mock
private Execution mockExecution;
// TODO add more tests!!!
@Test
@SuppressWarnings("unchecked")
public void executeWithResults() throws Exception {
Object[] args = { "one", "two", "three" };
List<Object> results = Arrays.asList(args);
Function mockFunction = mock(Function.class, "MockFunction");
ResultCollector mockResultCollector = mock(ResultCollector.class, "MockResultCollector");
when(mockExecution.withArgs(eq(args))).thenReturn(mockExecution);
when(mockExecution.execute(eq(mockFunction))).thenReturn(mockResultCollector);
when(mockFunction.hasResult()).thenReturn(true);
when(mockResultCollector.getResult(500, TimeUnit.MILLISECONDS)).thenReturn(results);
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
@Override protected Execution getExecution() {
return mockExecution;
}
};
Iterable<Object> actualResults = functionExecution.setFunction(mockFunction)
.setArgs(args).setTimeout(500).execute();
assertThat(actualResults, is(notNullValue()));
assertThat(actualResults, is(equalTo((Iterable<Object>) results)));
verify(mockExecution, times(1)).withArgs(eq(args));
verify(mockExecution, never()).withCollector(any(ResultCollector.class));
verify(mockExecution, never()).withFilter(any(Set.class));
verify(mockExecution, times(1)).execute(eq(mockFunction));
verify(mockExecution, never()).execute(any(String.class));
verify(mockResultCollector, times(1)).getResult(500, TimeUnit.MILLISECONDS);
verify(mockResultCollector, never()).getResult();
}
@Test
public void executeAndExtractWithSingleResult() {
final List<String> results = Collections.singletonList("test");
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
@Override protected Execution getExecution() {
return mockExecution;
}
@SuppressWarnings("unchecked")
@Override <T> Iterable<T> execute() {
return (Iterable<T>) results;
}
};
assertThat(String.valueOf(functionExecution.executeAndExtract()), is(equalTo("test")));
}
@Test
public void executeAndExtractWithMultipleResults() {
final List<String> results = Arrays.asList("one", "two", "three");
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
@Override protected Execution getExecution() {
return mockExecution;
}
@SuppressWarnings("unchecked")
@Override <T> Iterable<T> execute() {
return (Iterable<T>) results;
}
};
assertThat(String.valueOf(functionExecution.executeAndExtract()), is(equalTo("one")));
}
@Test
public void executeAndExtractWithNullResults() {
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
@Override protected Execution getExecution() {
return mockExecution;
}
@SuppressWarnings("unchecked")
@Override <T> Iterable<T> execute() {
return null;
}
};
assertThat(functionExecution.executeAndExtract(), is(nullValue()));
}
@Test
public void executeAndExtractWithNoResults() {
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
@Override protected Execution getExecution() {
return mockExecution;
}
@SuppressWarnings("unchecked")
@Override <T> Iterable<T> execute() {
return Collections.emptyList();
}
};
assertThat(functionExecution.executeAndExtract(), is(nullValue()));
}
@Test
public void executeAndExtractWithThrowsException() {
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
@Override protected Execution getExecution() {
return mockExecution;
}
@SuppressWarnings("unchecked")
@Override <T> Iterable<T> execute() {
return Collections.singletonList((T) new IllegalArgumentException("test"));
}
};
expectedException.expect(FunctionException.class);
expectedException.expectCause(isA(IllegalArgumentException.class));
expectedException.expectMessage(containsString("Execution of Function with ID 'TestFunction' failed"));
functionExecution.setFunctionId("TestFunction").executeAndExtract();
}
}

View File

@@ -0,0 +1,224 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.ResultCollector;
/**
* The AbstractFunctionTemplateTest class is a test suite of test cases testing the contract and functionality
* of the AbstractFunctionTemplate class.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution
* @see org.springframework.data.gemfire.function.execution.AbstractFunctionTemplate
* @see com.gemstone.gemfire.cache.execute.Function
* @see com.gemstone.gemfire.cache.execute.ResultCollector
* @since 1.7.0
*/
@RunWith(MockitoJUnitRunner.class)
public class AbstractFunctionTemplateTest {
@Mock
private AbstractFunctionExecution mockFunctionExecution;
@Mock
Function mockFunction;
@Mock
private ResultCollector mockResultCollector;
@Test
public void executeWithFunctionAndArgs() {
Object[] args = { "test", "testing", "tested" };
List<Object> results = Arrays.asList(args);
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setFunction(mockFunction)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.execute()).thenReturn(results);
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
@Override protected AbstractFunctionExecution getFunctionExecution() {
return mockFunctionExecution;
}
};
functionTemplate.setResultCollector(mockResultCollector);
functionTemplate.setTimeout(500);
Iterable<Object> actualResults = functionTemplate.execute(mockFunction, args);
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
assertThat(actualResults, is(notNullValue()));
assertThat(actualResults, is(equalTo((Iterable<Object>) results)));
verify(mockFunctionExecution, times(1)).setArgs(args);
verify(mockFunctionExecution, times(1)).setFunction(mockFunction);
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
verify(mockFunctionExecution, times(1)).setTimeout(500);
verify(mockFunctionExecution, times(1)).execute();
}
@Test
public void executeAndExtractWithFunctionAndArgs() {
Object[] args = { "test", "testing", "tested" };
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setFunction(mockFunction)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.executeAndExtract()).thenReturn(args[0]);
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
@Override protected AbstractFunctionExecution getFunctionExecution() {
return mockFunctionExecution;
}
};
functionTemplate.setResultCollector(mockResultCollector);
functionTemplate.setTimeout(500);
String result = functionTemplate.executeAndExtract(mockFunction, args);
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
assertThat(result, is(notNullValue()));
assertThat(result, is(equalTo("test")));
verify(mockFunctionExecution, times(1)).setArgs(args);
verify(mockFunctionExecution, times(1)).setFunction(mockFunction);
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
verify(mockFunctionExecution, times(1)).setTimeout(500);
verify(mockFunctionExecution, times(1)).executeAndExtract();
}
@Test
public void executeWithFunctionIdAndArgs() {
Object[] args = { "test", "testing", "tested" };
List<Object> results = Arrays.asList(args);
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setFunctionId("TestFunction")).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.execute()).thenReturn(results);
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
@Override protected AbstractFunctionExecution getFunctionExecution() {
return mockFunctionExecution;
}
};
functionTemplate.setResultCollector(mockResultCollector);
functionTemplate.setTimeout(500);
Iterable<Object> actualResults = functionTemplate.execute("TestFunction", args);
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
assertThat(actualResults, is(notNullValue()));
assertThat(actualResults, is(equalTo((Iterable<Object>) results)));
verify(mockFunctionExecution, times(1)).setArgs(args);
verify(mockFunctionExecution, times(1)).setFunctionId("TestFunction");
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
verify(mockFunctionExecution, times(1)).setTimeout(500);
verify(mockFunctionExecution, times(1)).execute();
}
@Test
public void executeAndExtractWithFunctionIdAndArgs() {
Object[] args = { "test", "testing", "tested" };
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setFunctionId("TestFunction")).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.executeAndExtract()).thenReturn(args[0]);
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
@Override protected AbstractFunctionExecution getFunctionExecution() {
return mockFunctionExecution;
}
};
functionTemplate.setResultCollector(mockResultCollector);
functionTemplate.setTimeout(500);
String result = functionTemplate.executeAndExtract("TestFunction", args);
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
assertThat(result, is(notNullValue()));
assertThat(result, is(equalTo("test")));
verify(mockFunctionExecution, times(1)).setArgs(args);
verify(mockFunctionExecution, times(1)).setFunctionId("TestFunction");
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
verify(mockFunctionExecution, times(1)).setTimeout(500);
verify(mockFunctionExecution, times(1)).executeAndExtract();
}
@Test
public void executeWithNoResultWithFunctionIdAndArgs() {
Object[] args = { "test", "testing", "tested" };
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setFunctionId("TestFunction")).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
when(mockFunctionExecution.execute(eq(false))).thenReturn(null);
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
@Override protected AbstractFunctionExecution getFunctionExecution() {
return mockFunctionExecution;
}
};
functionTemplate.setResultCollector(mockResultCollector);
functionTemplate.setTimeout(500);
functionTemplate.executeWithNoResult("TestFunction", args);
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
verify(mockFunctionExecution, times(1)).setArgs(args);
verify(mockFunctionExecution, times(1)).setFunctionId("TestFunction");
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
verify(mockFunctionExecution, times(1)).setTimeout(500);
verify(mockFunctionExecution, times(1)).execute(eq(false));
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.function.sample;
import org.springframework.data.gemfire.function.annotation.OnServer;
/**
* The ExceptionThrowingFunctionExecution interface defines a GemFire Function that throws a RuntimeException.
*
* @author John Blum
* @see org.springframework.data.gemfire.function.annotation.OnServer
* @since 1.7.0
*/
@OnServer
@SuppressWarnings("unused")
public interface ExceptionThrowingFunctionExecution {
Integer exceptionThrowingFunction();
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
<util:properties id="gemfireProperties">
<prop key="log-level">config</prop>
</util:properties>
<gfe:pool id="serverPool">
<gfe:server host="localhost" port="12480"/>
</gfe:pool>
<gfe:client-cache properties-ref="gemfireProperties" pool-name="serverPool"/>
<gfe-data:function-executions base-package="org.springframework.data.gemfire.function.sample">
<gfe-data:include-filter type="assignable" expression="org.springframework.data.gemfire.function.sample.ExceptionThrowingFunctionExecution"/>
</gfe-data:function-executions>
</beans>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
<util:properties id="serverProperties">
<prop key="server.bind-address">localhost</prop>
<prop key="server.hostname-for-clients">localhost</prop>
<prop key="server.max-connections">1</prop>
<prop key="server.port">12480</prop>
</util:properties>
<context:property-placeholder properties-ref="serverProperties"/>
<util:properties id="gemfireProperties">
<prop key="name">ExceptionThrowingFunctionExecutionIntegrationTestServer</prop>
<prop key="mcast-port">0</prop>
<prop key="log-level">warning</prop>
</util:properties>
<gfe:cache properties-ref="gemfireProperties" lazy-init="false"/>
<gfe:cache-server auto-startup="true" bind-address="${server.bind-address}" port="${server.port}"
host-name-for-clients="${server.hostname-for-clients}" max-connections="${server.max-connections}"/>
<gfe:function-service>
<gfe:function>
<bean class="org.springframework.data.gemfire.function.ExceptionThrowingFunctionExecutionIntegrationTest$ExceptionThrowingFunction"/>
</gfe:function>
</gfe:function-service>
</beans>