SGF-409 - Modify the GemfireDataSourcePostProcessor (basis for <gfe:datasource>) to not assume a GemFire Server was configured and bootstrapped with Spring and subsequently that the SDG ListRegionsOnServerFunction was registered.
Refactored the GemfireDataSourcePostProcessorTest class test cases based on the new implementation of the GemfireDataSourcePostProcessor BeanFactoryPostProcessor, which uses the GemFire internal GetRegionsFunction GemFire Function as a fallback when the ListRegionsOnServerFunction has not been registered or is not available. In addition, added 2 integration tests to test a Spring Data GemFire ClientCache connecting to a Spring-configured GemFire Server and non-Spring-configured GemFire Server asserting that client PROXY Region beans are appropriately created in the Spring ApplicationContext.
This commit is contained in:
@@ -12,6 +12,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.gemfire.client;
|
package org.springframework.data.gemfire.client;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
@@ -19,7 +23,6 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
|||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate;
|
import org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate;
|
||||||
import org.springframework.data.gemfire.support.ListRegionsOnServerFunction;
|
import org.springframework.data.gemfire.support.ListRegionsOnServerFunction;
|
||||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
@@ -28,31 +31,42 @@ import com.gemstone.gemfire.cache.client.ClientCache;
|
|||||||
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
|
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
|
||||||
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
||||||
import com.gemstone.gemfire.cache.execute.Function;
|
import com.gemstone.gemfire.cache.execute.Function;
|
||||||
import com.gemstone.gemfire.management.internal.cli.functions.ListFunctionFunction;
|
import com.gemstone.gemfire.management.internal.cli.domain.RegionInformation;
|
||||||
|
import com.gemstone.gemfire.management.internal.cli.functions.GetRegionsFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link BeanFactoryPostProcessor} to register a Client Region bean, if necessary, for each Region accessible
|
* A Spring {@link BeanFactoryPostProcessor} used to register a Client Region Proxy bean for each Region
|
||||||
* to a Gemfire data source. If the Region is already defined, the definition will not be overridden.
|
* accessible to a GemFire DataSource. If the Region is already defined, the bean definition will not be overridden.
|
||||||
*
|
*
|
||||||
* @author David Turanski
|
* @author David Turanski
|
||||||
* @author John Blum
|
* @author John Blum
|
||||||
|
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
|
||||||
|
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
||||||
|
* @see org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate
|
||||||
|
* @see org.springframework.data.gemfire.support.ListRegionsOnServerFunction
|
||||||
|
* @see com.gemstone.gemfire.cache.Region
|
||||||
|
* @see com.gemstone.gemfire.cache.client.ClientCache
|
||||||
|
* @see com.gemstone.gemfire.cache.client.ClientRegionFactory
|
||||||
|
* @see com.gemstone.gemfire.cache.execute.Function
|
||||||
|
* @see com.gemstone.gemfire.management.internal.cli.functions.GetRegionsFunction
|
||||||
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor {
|
public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor {
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
private final ClientCache cache;
|
private final ClientCache clientCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance of the GemfireDataSourcePostProcessor BeanFactoryPostProcessor class initialized
|
* Constructs an instance of the GemfireDataSourcePostProcessor BeanFactoryPostProcessor class initialized
|
||||||
* with the specified GemFire ClientCache instance for creating client PROXY Regions for all data Regions
|
* with the specified GemFire ClientCache instance for creating client PROXY Regions for all data Regions
|
||||||
* configured in the GemFire cluster.
|
* configured in the GemFire cluster.
|
||||||
*
|
*
|
||||||
* @param cache the GemFire ClientCache instance.
|
* @param clientCache the GemFire ClientCache instance.
|
||||||
* @see com.gemstone.gemfire.cache.client.ClientCache
|
* @see com.gemstone.gemfire.cache.client.ClientCache
|
||||||
*/
|
*/
|
||||||
public GemfireDataSourcePostProcessor(final ClientCache cache) {
|
public GemfireDataSourcePostProcessor(final ClientCache clientCache) {
|
||||||
this.cache = cache;
|
this.clientCache = clientCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -61,29 +75,54 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||||
if (isFunctionAvailable(ListRegionsOnServerFunction.ID)) {
|
createClientRegionProxies(beanFactory, regionNames());
|
||||||
createClientProxyRegions(beanFactory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO what happens when the GemFire cluster contains a mix of "pure" GemFire Servers (non-Spring configured)
|
|
||||||
// as well as Spring configured/bootstrapped GemFire Servers?
|
|
||||||
boolean isFunctionAvailable(String targetFunctionId) {
|
|
||||||
for (String functionId : this.<String>execute(new ListFunctionFunction())) {
|
|
||||||
if (functionId.equals(targetFunctionId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc) */
|
/* (non-Javadoc) */
|
||||||
void createClientProxyRegions(ConfigurableListableBeanFactory beanFactory) {
|
Iterable<String> regionNames() {
|
||||||
Iterable<String> regionNames = execute(new ListRegionsOnServerFunction());
|
try {
|
||||||
|
return execute(new ListRegionsOnServerFunction());
|
||||||
|
}
|
||||||
|
catch (Exception ignore) {
|
||||||
|
try {
|
||||||
|
Object results = execute(new GetRegionsFunction());
|
||||||
|
List<String> regionNames = Collections.emptyList();
|
||||||
|
|
||||||
|
if (containsRegionInformation(results)) {
|
||||||
|
Object[] resultsArray = (Object[]) results;
|
||||||
|
|
||||||
|
regionNames = new ArrayList<String>(resultsArray.length);
|
||||||
|
|
||||||
|
for (Object result : resultsArray) {
|
||||||
|
regionNames.add(((RegionInformation) result).getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return regionNames;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
log("Failed to determine the Regions available on the Server: %n%1$s", e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc) */
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
<T> T execute(Function gemfireFunction, Object... arguments) {
|
||||||
|
return new GemfireOnServersFunctionTemplate(clientCache).executeAndExtract(gemfireFunction, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc) */
|
||||||
|
boolean containsRegionInformation(Object results) {
|
||||||
|
return (results instanceof Object[] && ((Object[]) results).length > 0
|
||||||
|
&& ((Object[]) results)[0] instanceof RegionInformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc) */
|
||||||
|
void createClientRegionProxies(ConfigurableListableBeanFactory beanFactory, Iterable<String> regionNames) {
|
||||||
if (regionNames.iterator().hasNext()) {
|
if (regionNames.iterator().hasNext()) {
|
||||||
ClientRegionFactory<?, ?> clientRegionFactory = cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
|
ClientRegionFactory<?, ?> clientRegionFactory = clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY);
|
||||||
|
|
||||||
for (String regionName : regionNames) {
|
for (String regionName : regionNames) {
|
||||||
boolean createRegion = true;
|
boolean createRegion = true;
|
||||||
@@ -110,15 +149,7 @@ public class GemfireDataSourcePostProcessor implements BeanFactoryPostProcessor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc) */
|
/* (non-Javadoc) */
|
||||||
<T> Iterable<T> execute(Function gemfireFunction, Object... arguments) {
|
void log(String message, Object... arguments) {
|
||||||
GemfireOnServersFunctionTemplate functionTemplate = new GemfireOnServersFunctionTemplate(cache);
|
|
||||||
|
|
||||||
return CollectionUtils.nullSafeIterable(
|
|
||||||
functionTemplate.<Iterable<T>>executeAndExtract(gemfireFunction, arguments));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc) */
|
|
||||||
private void log(String message, Object... arguments) {
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(String.format(message, arguments));
|
logger.debug(String.format(message, arguments));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* 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.client;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.data.gemfire.fork.ServerProcess;
|
||||||
|
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.Region;
|
||||||
|
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GemFireDataSourceIntegrationTest class is a test suite of test cases testing the contract and functionality
|
||||||
|
* of the <gfe-data:datasource> element in the context of a GemFire cluster running both native,
|
||||||
|
* non-Spring configured GemFire Servers in a addition to Spring configured and bootstrapped GemFire Server.
|
||||||
|
*
|
||||||
|
* @author John Blum
|
||||||
|
* @see org.junit.Test
|
||||||
|
* @see org.junit.runner.RunWith
|
||||||
|
* @see org.springframework.data.gemfire.client.GemfireDataSourcePostProcessor
|
||||||
|
* @see org.springframework.context.ApplicationContext
|
||||||
|
* @see org.springframework.test.context.ContextConfiguration
|
||||||
|
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||||
|
* @see com.gemstone.gemfire.cache.Region
|
||||||
|
* @see com.gemstone.gemfire.cache.client.ClientCache
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration
|
||||||
|
@SuppressWarnings({ "rawtypes", "unused"})
|
||||||
|
public class GemFireDataSourceIntegrationTest {
|
||||||
|
|
||||||
|
private static ProcessWrapper serverProcess;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ClientCache gemfireClientCache;
|
||||||
|
|
||||||
|
@Resource(name = "LocalRegion")
|
||||||
|
private Region localRegion;
|
||||||
|
|
||||||
|
@Resource(name = "ServerRegion")
|
||||||
|
private Region serverRegion;
|
||||||
|
|
||||||
|
@Resource(name = "ExclusiveServerRegion")
|
||||||
|
private Region exclusiveServerRegion;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupBeforeClass() throws IOException {
|
||||||
|
String serverName = "GemFireDataSourceSpringBasedServer";
|
||||||
|
|
||||||
|
File serverWorkingDirectory = new File(FileSystemUtils.WORKING_DIRECTORY, serverName.toLowerCase());
|
||||||
|
|
||||||
|
Assert.isTrue(serverWorkingDirectory.isDirectory() || serverWorkingDirectory.mkdirs());
|
||||||
|
|
||||||
|
List<String> arguments = new ArrayList<String>();
|
||||||
|
|
||||||
|
arguments.add(String.format("-Dgemfire.name=%1$s", serverName));
|
||||||
|
arguments.add("/org/springframework/data/gemfire/client/GemFireDataSourceIntegrationTest-server-context.xml");
|
||||||
|
|
||||||
|
serverProcess = ProcessExecutor.launch(serverWorkingDirectory, ServerProcess.class,
|
||||||
|
arguments.toArray(new String[arguments.size()]));
|
||||||
|
|
||||||
|
waitForProcessStart(TimeUnit.SECONDS.toMillis(20), serverProcess, ServerProcess.getServerProcessControlFilename());
|
||||||
|
|
||||||
|
System.out.println("Spring configured/bootstrapped GemFire Cache Server Process for ClientCache DataSource Test should be running...");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void waitForProcessStart(final long milliseconds, final ProcessWrapper process, final String processControlFilename) {
|
||||||
|
ThreadUtils.timedWait(milliseconds, TimeUnit.MILLISECONDS.toMillis(500), new ThreadUtils.WaitCondition() {
|
||||||
|
private File processControlFile = new File(process.getWorkingDirectory(), processControlFilename);
|
||||||
|
|
||||||
|
@Override public boolean waiting() {
|
||||||
|
return !processControlFile.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertRegion(Region actualRegion, String expectedRegionName) {
|
||||||
|
assertThat(actualRegion, is(not(nullValue())));
|
||||||
|
assertThat(actualRegion.getName(), is(equalTo(expectedRegionName)));
|
||||||
|
assertThat(actualRegion.getFullPath(), is(equalTo(String.format("%1$s%2$s",
|
||||||
|
Region.SEPARATOR, expectedRegionName))));
|
||||||
|
assertThat(gemfireClientCache.getRegion(actualRegion.getFullPath()), is(sameInstance(actualRegion)));
|
||||||
|
assertThat(applicationContext.containsBean(expectedRegionName), is(true));
|
||||||
|
assertThat(applicationContext.getBean(expectedRegionName, Region.class), is(sameInstance(actualRegion)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void clientProxyRegionBeansExist() {
|
||||||
|
assertRegion(localRegion, "LocalRegion");
|
||||||
|
assertRegion(serverRegion, "ServerRegion");
|
||||||
|
assertRegion(exclusiveServerRegion, "ExclusiveServerRegion");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* 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.client;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.data.gemfire.fork.GemFireBasedServerProcess;
|
||||||
|
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.Region;
|
||||||
|
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GemFireDataSourceUsingNonSpringConfiguredGemFireServerIntegrationTest class is a test suite of test cases
|
||||||
|
* testing the contract and functionality of the GemfireDataSourcePostProcessor using the <gfe-data:datasource>
|
||||||
|
* element in Spring config to setup a GemFire ClientCache connecting to a native, non-Spring configured GemFire Server
|
||||||
|
* as the DataSource to assert that client Region Proxies are registered as Spring beans
|
||||||
|
* in the Spring ApplicationContext correctly.
|
||||||
|
*
|
||||||
|
* @author John Blum
|
||||||
|
* @see org.springframework.data.gemfire.client.GemfireDataSourcePostProcessor
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration
|
||||||
|
@SuppressWarnings({ "rawtypes", "unused"})
|
||||||
|
public class GemFireDataSourceUsingNonSpringConfiguredGemFireServerIntegrationTest {
|
||||||
|
|
||||||
|
private static ProcessWrapper serverProcess;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ClientCache gemfireClientCache;
|
||||||
|
|
||||||
|
@Resource(name = "LocalRegion")
|
||||||
|
private Region localRegion;
|
||||||
|
|
||||||
|
@Resource(name = "ServerRegion")
|
||||||
|
private Region serverRegion;
|
||||||
|
|
||||||
|
@Resource(name = "AnotherServerRegion")
|
||||||
|
private Region anotherServerRegion;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupBeforeClass() throws IOException {
|
||||||
|
String serverName = "GemFireDataSourceGemFireBasedServer";
|
||||||
|
|
||||||
|
File serverWorkingDirectory = new File(FileSystemUtils.WORKING_DIRECTORY, serverName.toLowerCase());
|
||||||
|
|
||||||
|
Assert.isTrue(serverWorkingDirectory.isDirectory() || serverWorkingDirectory.mkdirs());
|
||||||
|
|
||||||
|
List<String> arguments = new ArrayList<String>(5);
|
||||||
|
|
||||||
|
arguments.add(String.format("-Dgemfire.name=%1$s", serverName));
|
||||||
|
arguments.add(String.format("-Dgemfire.mcast-port=%1$s", "0"));
|
||||||
|
arguments.add(String.format("-Dgemfire.log-level=%1$s", "warning"));
|
||||||
|
arguments.add(String.format("-Dgemfire.cache-xml-file=%1$s", "gemfire-datasource-integration-test-cache.xml"));
|
||||||
|
|
||||||
|
serverProcess = ProcessExecutor.launch(serverWorkingDirectory, GemFireBasedServerProcess.class,
|
||||||
|
arguments.toArray(new String[arguments.size()]));
|
||||||
|
|
||||||
|
waitForProcessStart(TimeUnit.SECONDS.toMillis(20), serverProcess, GemFireBasedServerProcess.getServerProcessControlFilename());
|
||||||
|
|
||||||
|
System.out.println("GemFire-based Cache Server Process for ClientCache DataSource Test should be running and connected...");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void waitForProcessStart(final long milliseconds, final ProcessWrapper process, final String processControlFilename) {
|
||||||
|
ThreadUtils.timedWait(milliseconds, TimeUnit.MILLISECONDS.toMillis(500), new ThreadUtils.WaitCondition() {
|
||||||
|
private File processControlFile = new File(process.getWorkingDirectory(), processControlFilename);
|
||||||
|
|
||||||
|
@Override public boolean waiting() {
|
||||||
|
return !processControlFile.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertRegion(Region actualRegion, String expectedRegionName) {
|
||||||
|
assertThat(actualRegion, is(not(nullValue())));
|
||||||
|
assertThat(actualRegion.getName(), is(equalTo(expectedRegionName)));
|
||||||
|
assertThat(actualRegion.getFullPath(), is(equalTo(String.format("%1$s%2$s",
|
||||||
|
Region.SEPARATOR, expectedRegionName))));
|
||||||
|
assertThat(gemfireClientCache.getRegion(actualRegion.getFullPath()), is(sameInstance(actualRegion)));
|
||||||
|
assertThat(applicationContext.containsBean(expectedRegionName), is(true));
|
||||||
|
assertThat(applicationContext.getBean(expectedRegionName, Region.class), is(sameInstance(actualRegion)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void clientProxyRegionBeansExist() {
|
||||||
|
assertRegion(localRegion, "LocalRegion");
|
||||||
|
assertRegion(serverRegion, "ServerRegion");
|
||||||
|
assertRegion(anotherServerRegion, "AnotherServerRegion");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,9 +17,12 @@
|
|||||||
package org.springframework.data.gemfire.client;
|
package org.springframework.data.gemfire.client;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
import static org.hamcrest.CoreMatchers.nullValue;
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
@@ -31,9 +34,11 @@ import static org.mockito.Mockito.times;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@@ -43,12 +48,18 @@ import org.junit.rules.ExpectedException;
|
|||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.data.gemfire.support.ListRegionsOnServerFunction;
|
||||||
|
|
||||||
|
import com.gemstone.gemfire.cache.DataPolicy;
|
||||||
import com.gemstone.gemfire.cache.Region;
|
import com.gemstone.gemfire.cache.Region;
|
||||||
|
import com.gemstone.gemfire.cache.RegionAttributes;
|
||||||
|
import com.gemstone.gemfire.cache.Scope;
|
||||||
import com.gemstone.gemfire.cache.client.ClientCache;
|
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||||
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
|
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
|
||||||
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
||||||
import com.gemstone.gemfire.cache.execute.Function;
|
import com.gemstone.gemfire.cache.execute.Function;
|
||||||
|
import com.gemstone.gemfire.management.internal.cli.domain.RegionInformation;
|
||||||
|
import com.gemstone.gemfire.management.internal.cli.functions.GetRegionsFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GemfireDataSourcePostProcessor class is a test suite of test cases testing the contract and functionality
|
* The GemfireDataSourcePostProcessor class is a test suite of test cases testing the contract and functionality
|
||||||
@@ -63,7 +74,6 @@ import com.gemstone.gemfire.cache.execute.Function;
|
|||||||
* @see com.gemstone.gemfire.cache.Region
|
* @see com.gemstone.gemfire.cache.Region
|
||||||
* @see com.gemstone.gemfire.cache.client.ClientCache
|
* @see com.gemstone.gemfire.cache.client.ClientCache
|
||||||
* @see com.gemstone.gemfire.cache.client.ClientRegionFactory
|
* @see com.gemstone.gemfire.cache.client.ClientRegionFactory
|
||||||
* @see com.gemstone.gemfire.cache.execute.Function
|
|
||||||
* @since 1.7.0
|
* @since 1.7.0
|
||||||
*/
|
*/
|
||||||
public class GemfireDataSourcePostProcessorTest {
|
public class GemfireDataSourcePostProcessorTest {
|
||||||
@@ -71,75 +81,180 @@ public class GemfireDataSourcePostProcessorTest {
|
|||||||
@Rule
|
@Rule
|
||||||
public ExpectedException expectedException = ExpectedException.none();
|
public ExpectedException expectedException = ExpectedException.none();
|
||||||
|
|
||||||
private GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
protected RegionInformation newRegionInformation(Region<?, ?> region) {
|
||||||
@Override @SuppressWarnings("unchecked") <T> Iterable<T> execute(Function gemfireFunction, Object... arguments) {
|
return new RegionInformation(region, false);
|
||||||
return (Iterable<T>) Arrays.asList("FunctionOne", "FunctionTwo");
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected Region<Object, Object> mockRegion(String name) {
|
||||||
|
Region<Object, Object> mockRegion = mock(Region.class, name);
|
||||||
|
|
||||||
|
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class,
|
||||||
|
String.format("%1$s-RegionAttributes", name));
|
||||||
|
|
||||||
|
when(mockRegion.getFullPath()).thenReturn(String.format("%1$s%2$s", Region.SEPARATOR, name));
|
||||||
|
when(mockRegion.getName()).thenReturn(name);
|
||||||
|
when(mockRegion.getParentRegion()).thenReturn(null);
|
||||||
|
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
|
||||||
|
when(mockRegionAttributes.getDataPolicy()).thenReturn(DataPolicy.PARTITION);
|
||||||
|
when(mockRegionAttributes.getScope()).thenReturn(Scope.DISTRIBUTED_ACK);
|
||||||
|
|
||||||
|
return mockRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> List<T> asList(Iterable<T> iterable) {
|
||||||
|
List<T> list = new ArrayList<T>();
|
||||||
|
|
||||||
|
if (iterable != null) {
|
||||||
|
for (T element : iterable) {
|
||||||
|
list.add(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postProcessBeanFactoryWhenListRegionsOnServerFunctionIsAvailable() {
|
public void postProcessBeanFactoryCallsCreateClientRegionProxiesWithRegionNames() {
|
||||||
final AtomicBoolean createClientProxyRegionsCalled = new AtomicBoolean(false);
|
final AtomicBoolean createClientRegionProxiesCalled = new AtomicBoolean(false);
|
||||||
|
final ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "MockSpringBeanFactory");
|
||||||
final ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class,
|
final List<String> testRegionNames = Collections.singletonList("Test");
|
||||||
"MockStringBeanFactory");
|
|
||||||
|
|
||||||
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
||||||
@Override boolean isFunctionAvailable(String targetFunctionId) {
|
@Override Iterable<String> regionNames() {
|
||||||
return true;
|
return testRegionNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override void createClientProxyRegions(final ConfigurableListableBeanFactory beanFactory) {
|
@Override void createClientRegionProxies(ConfigurableListableBeanFactory beanFactory, Iterable<String> regionNames) {
|
||||||
assertThat(beanFactory, is(sameInstance(mockBeanFactory)));
|
assertThat(beanFactory, is(sameInstance(mockBeanFactory)));
|
||||||
createClientProxyRegionsCalled.compareAndSet(false, true);
|
assertSame(testRegionNames, regionNames);
|
||||||
|
createClientRegionProxiesCalled.compareAndSet(false, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
postProcessor.postProcessBeanFactory(mockBeanFactory);
|
postProcessor.postProcessBeanFactory(mockBeanFactory);
|
||||||
|
|
||||||
assertThat(createClientProxyRegionsCalled.get(), is(true));
|
assertThat(createClientRegionProxiesCalled.get(), is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postProcessBeanFactoryWhenListRegionsOnServerFunctionIsNotAvailable() {
|
public void regionNamesWithListRegionsOnServerFunction() {
|
||||||
final AtomicBoolean createClientProxyRegionsCalled = new AtomicBoolean(false);
|
final List<String> expectedRegionNames = Arrays.asList("ExampleOne", "ExampleTwo");
|
||||||
|
|
||||||
final ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class,
|
|
||||||
"MockStringBeanFactory");
|
|
||||||
|
|
||||||
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
||||||
@Override boolean isFunctionAvailable(String targetFunctionId) {
|
@Override @SuppressWarnings("unchecked") <T> T execute(Function gemfireFunction, Object... arguments) {
|
||||||
return false;
|
assertThat(gemfireFunction, is(instanceOf(ListRegionsOnServerFunction.class)));
|
||||||
}
|
return (T) expectedRegionNames;
|
||||||
|
|
||||||
@Override void createClientProxyRegions(final ConfigurableListableBeanFactory beanFactory) {
|
|
||||||
assertThat(beanFactory, is(sameInstance(mockBeanFactory)));
|
|
||||||
createClientProxyRegionsCalled.compareAndSet(false, true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
postProcessor.postProcessBeanFactory(mockBeanFactory);
|
Iterable<String> actualRegionNames = postProcessor.regionNames();
|
||||||
|
|
||||||
assertThat(createClientProxyRegionsCalled.get(), is(false));
|
assertSame(expectedRegionNames, actualRegionNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isFunctionAvailableWhenFunctionIsAvailable() {
|
public void regionNamesWithGetRegionsFunction() {
|
||||||
assertThat(postProcessor.isFunctionAvailable("FunctionOne"), is(true));
|
final List<String> expectedRegionNames = Arrays.asList("ExampleOne", "ExampleTwo");
|
||||||
|
|
||||||
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
||||||
|
@Override @SuppressWarnings("unchecked") <T> T execute(Function gemfireFunction, Object... arguments) {
|
||||||
|
if (gemfireFunction instanceof ListRegionsOnServerFunction) {
|
||||||
|
throw new RuntimeException("fail");
|
||||||
|
}
|
||||||
|
else if (gemfireFunction instanceof GetRegionsFunction) {
|
||||||
|
return (T) Arrays.asList(newRegionInformation(mockRegion(expectedRegionNames.get(0))),
|
||||||
|
newRegionInformation(mockRegion(expectedRegionNames.get(1)))).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(String.format("GemFire Function (%1$s) with ID (%2$s) not registered",
|
||||||
|
gemfireFunction.getClass().getName(), gemfireFunction.getId()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Iterable<String> actualRegionNames = postProcessor.regionNames();
|
||||||
|
|
||||||
|
assertThat(asList(actualRegionNames).containsAll(expectedRegionNames), is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isFunctionAvailableWhenFunctionIsNotAvailable() {
|
public void regionNamesWithGetRegionsFunctionReturningNoResults() {
|
||||||
assertThat(postProcessor.isFunctionAvailable("functionOne"), is(false));
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
||||||
assertThat(postProcessor.isFunctionAvailable("Functionone"), is(false));
|
@Override @SuppressWarnings("unchecked") <T> T execute(Function gemfireFunction, Object... arguments) {
|
||||||
assertThat(postProcessor.isFunctionAvailable("FuncOne"), is(false));
|
if (gemfireFunction instanceof ListRegionsOnServerFunction) {
|
||||||
assertThat(postProcessor.isFunctionAvailable("Function1"), is(false));
|
throw new RuntimeException("fail");
|
||||||
assertThat(postProcessor.isFunctionAvailable("FunctionUno"), is(false));
|
}
|
||||||
|
else if (gemfireFunction instanceof GetRegionsFunction) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(String.format("GemFire Function (%1$s) with ID (%2$s) not registered",
|
||||||
|
gemfireFunction.getClass().getName(), gemfireFunction.getId()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Iterable<String> actualRegionNames = postProcessor.regionNames();
|
||||||
|
|
||||||
|
assertThat(actualRegionNames, is(not(nullValue())));
|
||||||
|
assertThat(actualRegionNames.iterator(), (is(not(nullValue()))));
|
||||||
|
assertThat(actualRegionNames.iterator().hasNext(), is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void regionNamesWithGetRegionsFunctionThrowingException() {
|
||||||
|
final AtomicBoolean logMethodCalled = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(null) {
|
||||||
|
@Override @SuppressWarnings("unchecked") <T> T execute(Function gemfireFunction, Object... arguments) {
|
||||||
|
throw new IllegalArgumentException(String.format("GemFire Function (%1$s) with ID (%2$s) not registered",
|
||||||
|
gemfireFunction.getClass().getName(), gemfireFunction.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override void log(final String message, final Object... arguments) {
|
||||||
|
assertThat(message.startsWith("Failed to determine the Regions available on the Server:"), is(true));
|
||||||
|
logMethodCalled.compareAndSet(false, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Iterable<String> actualRegionNames = postProcessor.regionNames();
|
||||||
|
|
||||||
|
assertThat(actualRegionNames, is(not(nullValue())));
|
||||||
|
assertThat(actualRegionNames.iterator(), (is(not(nullValue()))));
|
||||||
|
assertThat(actualRegionNames.iterator().hasNext(), is(false));
|
||||||
|
assertThat(logMethodCalled.get(), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsRegionInformationIsTrue() {
|
||||||
|
assertThat(new GemfireDataSourcePostProcessor(null).containsRegionInformation(
|
||||||
|
new Object[] { newRegionInformation(mockRegion("Example")) }), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsRegionInformationWithListOfRegionInformationIsFalse() {
|
||||||
|
assertThat(new GemfireDataSourcePostProcessor(null).containsRegionInformation(
|
||||||
|
Arrays.asList(newRegionInformation(mockRegion("Example")))), is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsRegionInformationWithNonEmptyArrayContainingNonRegionInformationIsFalse() {
|
||||||
|
assertThat(new GemfireDataSourcePostProcessor(null).containsRegionInformation(new Object[] { "test" }),
|
||||||
|
is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsRegionInformationWithEmptyArrayIsFalse() {
|
||||||
|
assertThat(new GemfireDataSourcePostProcessor(null).containsRegionInformation(new Object[0]), is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsRegionInformationWithNullIsFalse() {
|
||||||
|
assertThat(new GemfireDataSourcePostProcessor(null).containsRegionInformation(null), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void createClientProxyRegions() {
|
public void createClientRegionProxies() {
|
||||||
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache");
|
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache");
|
||||||
|
|
||||||
ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory");
|
ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory");
|
||||||
@@ -163,17 +278,13 @@ public class GemfireDataSourcePostProcessorTest {
|
|||||||
}
|
}
|
||||||
}).when(mockClientRegionFactory).create(any(String.class));
|
}).when(mockClientRegionFactory).create(any(String.class));
|
||||||
|
|
||||||
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "SpringBeanFactory");
|
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "MockSpringBeanFactory");
|
||||||
|
|
||||||
when(mockBeanFactory.containsBean(any(String.class))).thenReturn(false);
|
when(mockBeanFactory.containsBean(any(String.class))).thenReturn(false);
|
||||||
|
|
||||||
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache) {
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache);
|
||||||
@Override <T> Iterable<T> execute(final Function gemfireFunction, final Object... arguments) {
|
|
||||||
return (Iterable<T>) Arrays.asList("RegionOne", "RegionTwo");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
postProcessor.createClientProxyRegions(mockBeanFactory);
|
postProcessor.createClientRegionProxies(mockBeanFactory, regionMap.keySet());
|
||||||
|
|
||||||
verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY));
|
verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY));
|
||||||
verify(mockClientRegionFactory, times(1)).create(eq("RegionOne"));
|
verify(mockClientRegionFactory, times(1)).create(eq("RegionOne"));
|
||||||
@@ -184,7 +295,7 @@ public class GemfireDataSourcePostProcessorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void createClientProxyRegionWhenRegionBeanExists() {
|
public void createClientRegionProxiesWhenRegionBeanExists() {
|
||||||
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache");
|
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache");
|
||||||
|
|
||||||
ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory");
|
ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory");
|
||||||
@@ -194,18 +305,14 @@ public class GemfireDataSourcePostProcessorTest {
|
|||||||
|
|
||||||
Region mockRegion = mock(Region.class, "MockGemFireRegion");
|
Region mockRegion = mock(Region.class, "MockGemFireRegion");
|
||||||
|
|
||||||
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "SpringBeanFactory");
|
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "MockSpringBeanFactory");
|
||||||
|
|
||||||
when(mockBeanFactory.containsBean(any(String.class))).thenReturn(true);
|
when(mockBeanFactory.containsBean(any(String.class))).thenReturn(true);
|
||||||
when(mockBeanFactory.getBean(eq("Example"))).thenReturn(mockRegion);
|
when(mockBeanFactory.getBean(eq("Example"))).thenReturn(mockRegion);
|
||||||
|
|
||||||
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache) {
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache);
|
||||||
@Override <T> Iterable<T> execute(final Function gemfireFunction, final Object... arguments) {
|
|
||||||
return (Iterable<T>) Collections.singletonList("Example");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
postProcessor.createClientProxyRegions(mockBeanFactory);
|
postProcessor.createClientRegionProxies(mockBeanFactory, Arrays.asList("Example"));
|
||||||
|
|
||||||
verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY));
|
verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY));
|
||||||
verify(mockClientRegionFactory, never()).create(any(String.class));
|
verify(mockClientRegionFactory, never()).create(any(String.class));
|
||||||
@@ -214,7 +321,7 @@ public class GemfireDataSourcePostProcessorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void createClientProxyRegionWhenBeanOfDifferentTypeWithSameNameRegistered() {
|
public void createClientRegionProxiesWhenBeanOfDifferentTypeWithSameNameAsRegionIsRegistered() {
|
||||||
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache");
|
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache");
|
||||||
|
|
||||||
ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory");
|
ClientRegionFactory mockClientRegionFactory = mock(ClientRegionFactory.class, "MockGemFireClientRegionFactory");
|
||||||
@@ -222,16 +329,12 @@ public class GemfireDataSourcePostProcessorTest {
|
|||||||
when(mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.PROXY))).thenReturn(
|
when(mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.PROXY))).thenReturn(
|
||||||
mockClientRegionFactory);
|
mockClientRegionFactory);
|
||||||
|
|
||||||
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "SpringBeanFactory");
|
ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, "MockSpringBeanFactory");
|
||||||
|
|
||||||
when(mockBeanFactory.containsBean(any(String.class))).thenReturn(true);
|
when(mockBeanFactory.containsBean(any(String.class))).thenReturn(true);
|
||||||
when(mockBeanFactory.getBean(eq("Example"))).thenReturn(new Object());
|
when(mockBeanFactory.getBean(any(String.class))).thenReturn(new Object());
|
||||||
|
|
||||||
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache) {
|
GemfireDataSourcePostProcessor postProcessor = new GemfireDataSourcePostProcessor(mockClientCache);
|
||||||
@Override <T> Iterable<T> execute(final Function gemfireFunction, final Object... arguments) {
|
|
||||||
return (Iterable<T>) Collections.singletonList("Example");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expectedException.expect(IllegalArgumentException.class);
|
expectedException.expect(IllegalArgumentException.class);
|
||||||
@@ -239,7 +342,7 @@ public class GemfireDataSourcePostProcessorTest {
|
|||||||
expectedException.expectMessage(is(equalTo(String.format(
|
expectedException.expectMessage(is(equalTo(String.format(
|
||||||
"Cannot create a client PROXY Region bean named '%1$s'. A bean with this name of type '%2$s' already exists.",
|
"Cannot create a client PROXY Region bean named '%1$s'. A bean with this name of type '%2$s' already exists.",
|
||||||
"Example", Object.class.getName()))));
|
"Example", Object.class.getName()))));
|
||||||
postProcessor.createClientProxyRegions(mockBeanFactory);
|
postProcessor.createClientRegionProxies(mockBeanFactory, Arrays.asList("Example"));
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY));
|
verify(mockClientCache, times(1)).createClientRegionFactory(eq(ClientRegionShortcut.PROXY));
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.fork;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.springframework.data.gemfire.process.support.ProcessUtils;
|
||||||
|
import org.springframework.data.gemfire.test.support.FileSystemUtils;
|
||||||
|
|
||||||
|
import com.gemstone.gemfire.distributed.ServerLauncher;
|
||||||
|
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GemFireBasedServerProcess class is a main Java class used to launch a GemFire Server
|
||||||
|
* using GemFire's ServerLauncher API.
|
||||||
|
*
|
||||||
|
* @author John Blum
|
||||||
|
* @see com.gemstone.gemfire.distributed.ServerLauncher
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public class GemFireBasedServerProcess {
|
||||||
|
|
||||||
|
protected static final String DEFAULT_GEMFIRE_MEMBER_NAME = "SpringDataGemFire-Server";
|
||||||
|
protected static final String DEFAULT_HTTP_SERVICE_PORT = "0";
|
||||||
|
protected static final String DEFAULT_LOG_LEVEL = "warning";
|
||||||
|
protected static final String DEFAULT_USE_CLUSTER_CONFIGURATION = "false";
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws Throwable {
|
||||||
|
runServer(args);
|
||||||
|
|
||||||
|
registerShutdownHook();
|
||||||
|
|
||||||
|
ProcessUtils.writePid(new File(FileSystemUtils.WORKING_DIRECTORY, getServerProcessControlFilename()),
|
||||||
|
ProcessUtils.currentPid());
|
||||||
|
|
||||||
|
ProcessUtils.waitForStopSignal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getServerProcessControlFilename() {
|
||||||
|
return GemFireBasedServerProcess.class.getSimpleName().toLowerCase().concat(".pid");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerLauncher runServer(final String[] args) {
|
||||||
|
ServerLauncher serverLauncher = buildServerLauncher(args);
|
||||||
|
|
||||||
|
// start the GemFire Server process...
|
||||||
|
serverLauncher.start();
|
||||||
|
|
||||||
|
return serverLauncher;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerLauncher buildServerLauncher(final String[] args) {
|
||||||
|
return new ServerLauncher.Builder(args)
|
||||||
|
.setMemberName(System.getProperty("gemfire.name", DEFAULT_GEMFIRE_MEMBER_NAME))
|
||||||
|
.setCommand(ServerLauncher.Command.START)
|
||||||
|
.setDisableDefaultServer(true)
|
||||||
|
.setRedirectOutput(false)
|
||||||
|
.set(DistributionConfig.HTTP_SERVICE_PORT_NAME, System.getProperty("spring.gemfire.http-service-port",
|
||||||
|
DEFAULT_HTTP_SERVICE_PORT))
|
||||||
|
.set(DistributionConfig.JMX_MANAGER_NAME, String.valueOf(Boolean.TRUE))
|
||||||
|
.set(DistributionConfig.JMX_MANAGER_START_NAME, String.valueOf(Boolean.FALSE))
|
||||||
|
.set(DistributionConfig.LOG_LEVEL_NAME, System.getProperty("spring.gemfire.log-level", DEFAULT_LOG_LEVEL))
|
||||||
|
.set(DistributionConfig.USE_CLUSTER_CONFIGURATION_NAME, System.getProperty("spring.gemfire.use-cluster-configuration",
|
||||||
|
DEFAULT_USE_CLUSTER_CONFIGURATION))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerShutdownHook() {
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
ServerLauncher.getInstance().stop();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE cache PUBLIC "-//GemStone Systems, Inc.//GemFire Declarative Caching 8.0//EN"
|
||||||
|
"http://www.gemstone.com/dtd/cache8_0.dtd">
|
||||||
|
<cache>
|
||||||
|
<cache-server hostname-for-clients="localhost" port="42082"/>
|
||||||
|
<region name="ServerRegion" refid="PARTITION"/>
|
||||||
|
<region name="AnotherServerRegion" refid="REPLICATE"/>
|
||||||
|
</cache>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?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: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/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/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="client.properties">
|
||||||
|
<prop key="client.server.host">localhost</prop>
|
||||||
|
<prop key="client.server.port">42082</prop>
|
||||||
|
</util:properties>
|
||||||
|
|
||||||
|
<context:property-placeholder properties-ref="client.properties"/>
|
||||||
|
|
||||||
|
<gfe-data:datasource min-connections="1" max-connections="1">
|
||||||
|
<gfe-data:server host="${client.server.host}" port="${client.server.port}"/>
|
||||||
|
</gfe-data:datasource>
|
||||||
|
|
||||||
|
<gfe:client-region id="LocalRegion" shortcut="LOCAL"/>
|
||||||
|
|
||||||
|
<gfe:client-region id="ServerRegion" shortcut="CACHING_PROXY"/>
|
||||||
|
|
||||||
|
</beans>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?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="server.properties">
|
||||||
|
<prop key="gemfire.server.host">localhost</prop>
|
||||||
|
<prop key="gemfire.server.port">42082</prop>
|
||||||
|
</util:properties>
|
||||||
|
|
||||||
|
<context:property-placeholder properties-ref="server.properties"/>
|
||||||
|
|
||||||
|
<util:properties id="gemfireProperties">
|
||||||
|
<prop key="name">GemFireDataSourceIntegrationTestServer</prop>
|
||||||
|
<prop key="mcast-port">0</prop>
|
||||||
|
<prop key="log-level">warning</prop>
|
||||||
|
</util:properties>
|
||||||
|
|
||||||
|
<gfe:cache properties-ref="gemfireProperties"/>
|
||||||
|
|
||||||
|
<gfe:cache-server auto-startup="true" bind-address="${gemfire.server.host}" port="${gemfire.server.port}"
|
||||||
|
max-connections="1"/>
|
||||||
|
|
||||||
|
<gfe:replicated-region id="ServerRegion" persistent="false"/>
|
||||||
|
|
||||||
|
<gfe:partitioned-region id="ExclusiveServerRegion" persistent="false"/>
|
||||||
|
|
||||||
|
</beans>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?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: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/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/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="client.properties">
|
||||||
|
<prop key="client.server.host">localhost</prop>
|
||||||
|
<prop key="client.server.port">42082</prop>
|
||||||
|
</util:properties>
|
||||||
|
|
||||||
|
<context:property-placeholder properties-ref="client.properties"/>
|
||||||
|
|
||||||
|
<gfe-data:datasource min-connections="1" max-connections="1">
|
||||||
|
<gfe-data:server host="${client.server.host}" port="${client.server.port}"/>
|
||||||
|
</gfe-data:datasource>
|
||||||
|
|
||||||
|
<gfe:client-region id="LocalRegion" shortcut="LOCAL"/>
|
||||||
|
|
||||||
|
</beans>
|
||||||
Reference in New Issue
Block a user