Add @EnableClusterAware annotation configuration support allowing developers to seamlessly switch between local and client/server development environments.
Resolves gh-52.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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.geode.config.annotation;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableClusterConfiguration;
|
||||
|
||||
/**
|
||||
* The {@link ClusterAvailableConfiguration} class is a Spring {@link Configuration @Configuration} class that enables
|
||||
* configuration when an Apache Geode or Pivotal GemFire cluster of servers are available.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.context.annotation.Conditional
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableClusterConfiguration
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@Conditional(ClusterAvailableConfiguration.ClusterAvailableCondition.class)
|
||||
@EnableClusterConfiguration(requireHttps = false, useHttp = true)
|
||||
class ClusterAvailableConfiguration {
|
||||
|
||||
static final class ClusterAvailableCondition extends ClusterAwareConfiguration.ClusterAwareCondition { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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.geode.config.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpointList;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.geode.core.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link ClusterAwareConfiguration} class is a Spring {@link Configuration @Configuration} class imported by
|
||||
* {@link EnableClusterAware} used to determine whether a Spring Boot application using Apache Geode should run
|
||||
* in {@literal local-only mode} or {@literal client/server}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Annotation
|
||||
* @see java.net.Socket
|
||||
* @see java.net.SocketAddress
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.context.annotation.Condition
|
||||
* @see org.springframework.context.annotation.ConditionContext
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.core.env.ConfigurableEnvironment
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@Import({ ClusterAvailableConfiguration.class, ClusterNotAvailableConfiguration.class })
|
||||
public class ClusterAwareConfiguration extends AbstractAnnotationConfigSupport {
|
||||
|
||||
static final int DEFAULT_CACHE_SERVER_PORT = CacheServer.DEFAULT_PORT;
|
||||
static final int DEFAULT_LOCATOR_PORT = 10334;
|
||||
static final int DEFAULT_TIMEOUT_IN_MILLISECONDS = 500;
|
||||
|
||||
static final ClientRegionShortcut LOCAL_CLIENT_REGION_SHORTCUT = ClientRegionShortcut.LOCAL;
|
||||
|
||||
static final Logger logger = LoggerFactory.getLogger(ClusterAwareConfiguration.class);
|
||||
|
||||
static final String LOCALHOST = "localhost";
|
||||
static final String MATCHING_PROPERTY_PATTERN = "spring\\.data\\.gemfire\\.pool\\..*locators|servers";
|
||||
static final String SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY =
|
||||
"spring.data.gemfire.cache.client.region.shortcut";
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotationType() {
|
||||
return EnableClusterAware.class;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class ClusterAwareCondition implements Condition {
|
||||
|
||||
private static final AtomicReference<Boolean> clusterAvailable = new AtomicReference<>(null);
|
||||
|
||||
@Override
|
||||
public synchronized boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
|
||||
if (clusterAvailable.get() == null) {
|
||||
|
||||
Environment environment = context.getEnvironment();
|
||||
|
||||
ConnectionEndpointList connectionEndpoints = new ConnectionEndpointList(getDefaultConnectionEndpoints())
|
||||
.add(getConfiguredConnectionEndpoints(environment));
|
||||
|
||||
int connectionCount = countConnections(connectionEndpoints);
|
||||
|
||||
configureTopology(environment, connectionEndpoints, connectionCount);
|
||||
|
||||
clusterAvailable.set(isMatch(connectionEndpoints, connectionCount));
|
||||
}
|
||||
|
||||
return Boolean.TRUE.equals(clusterAvailable.get());
|
||||
}
|
||||
|
||||
List<ConnectionEndpoint> getDefaultConnectionEndpoints() {
|
||||
|
||||
return Arrays.asList(
|
||||
new ConnectionEndpoint(LOCALHOST, DEFAULT_CACHE_SERVER_PORT),
|
||||
new ConnectionEndpoint(LOCALHOST, DEFAULT_LOCATOR_PORT)
|
||||
);
|
||||
}
|
||||
|
||||
List<ConnectionEndpoint> getConfiguredConnectionEndpoints(Environment environment) {
|
||||
|
||||
List<ConnectionEndpoint> connectionEndpoints = new ArrayList<>();
|
||||
|
||||
if (environment instanceof ConfigurableEnvironment) {
|
||||
|
||||
ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment;
|
||||
|
||||
MutablePropertySources propertySources = configurableEnvironment.getPropertySources();
|
||||
|
||||
if (propertySources != null) {
|
||||
|
||||
Pattern pattern = Pattern.compile(MATCHING_PROPERTY_PATTERN);
|
||||
|
||||
for (PropertySource propertySource : propertySources) {
|
||||
if (propertySource instanceof EnumerablePropertySource) {
|
||||
|
||||
EnumerablePropertySource<?> enumerablePropertySource =
|
||||
(EnumerablePropertySource<?>) propertySource;
|
||||
|
||||
String[] propertyNames = enumerablePropertySource.getPropertyNames();
|
||||
|
||||
Arrays.stream(ArrayUtils.nullSafeArray(propertyNames, String.class))
|
||||
.filter(propertyName-> pattern.matcher(propertyName).find())
|
||||
.forEach(propertyName -> {
|
||||
|
||||
String propertyValue = environment.getProperty(propertyName);
|
||||
|
||||
if (StringUtils.hasText(propertyValue)) {
|
||||
|
||||
int defaultPort = propertyName.contains("servers")
|
||||
? DEFAULT_CACHE_SERVER_PORT
|
||||
: DEFAULT_LOCATOR_PORT;
|
||||
|
||||
String[] propertyValueArray = trim(propertyValue.split(","));
|
||||
|
||||
ConnectionEndpointList list =
|
||||
ConnectionEndpointList.parse(defaultPort, propertyValueArray);
|
||||
|
||||
connectionEndpoints.addAll(list);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return connectionEndpoints;
|
||||
}
|
||||
|
||||
// TODO: remove when DATAGEODE-228, a BUG in SDG, is fixed!
|
||||
private String[] trim(String[] array) {
|
||||
|
||||
array = ArrayUtils.nullSafeArray(array, String.class);
|
||||
|
||||
for (int index = 0; index < array.length; index++) {
|
||||
array[index] = StringUtils.trimAllWhitespace(array[index]);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
private boolean close(Socket socket) {
|
||||
return ObjectUtils.<Boolean>doOperationSafely(() -> {
|
||||
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}, cause -> false);
|
||||
}
|
||||
|
||||
int countConnections(ConnectionEndpointList connectionEndpoints) {
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (ConnectionEndpoint connectionEndpoint : connectionEndpoints) {
|
||||
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
socket = connect(connectionEndpoint);
|
||||
count++;
|
||||
}
|
||||
catch (IOException cause) {
|
||||
|
||||
if (getLogger().isInfoEnabled()) {
|
||||
getLogger().info("Failed to connect to {}", connectionEndpoint);
|
||||
}
|
||||
|
||||
if (getLogger().isDebugEnabled()) {
|
||||
getLogger().debug("Connection failure caused by:", cause);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
close(socket);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
Socket connect(ConnectionEndpoint connectionEndpoint) throws IOException {
|
||||
|
||||
SocketAddress socketAddress =
|
||||
new InetSocketAddress(connectionEndpoint.getHost(), connectionEndpoint.getPort());
|
||||
|
||||
Socket socket = new Socket();
|
||||
|
||||
socket.connect(socketAddress, DEFAULT_TIMEOUT_IN_MILLISECONDS);
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
void configureTopology(Environment environment, ConnectionEndpointList connectionEndpoints,
|
||||
int connectionCount) {
|
||||
|
||||
if (connectionCount < 1) {
|
||||
if (!environment.containsProperty(SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY)) {
|
||||
System.setProperty(SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY,
|
||||
LOCAL_CLIENT_REGION_SHORTCUT.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isMatch(ConnectionEndpointList connectionEndpoints, int connectionCount) {
|
||||
return connectionCount > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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.geode.config.annotation;
|
||||
|
||||
import static org.springframework.geode.config.annotation.ClusterAwareConfiguration.LOCAL_CLIENT_REGION_SHORTCUT;
|
||||
import static org.springframework.geode.config.annotation.ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY;
|
||||
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.RegionConfigurer;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link ClusterNotAvailableConfiguration} class is a Spring {@link Configuration @Configuration} class that
|
||||
* enables configuration when an Apache Geode or Pivotal GemFire cluster of servers is not available.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Conditional
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@Conditional(ClusterNotAvailableConfiguration.CusterNotAvailableCondition.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class ClusterNotAvailableConfiguration {
|
||||
|
||||
@Bean
|
||||
BeanPostProcessor localClientRegionBeanPostProcessor(Environment environment) {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Nullable @Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof ClientRegionFactoryBean) {
|
||||
|
||||
ClientRegionFactoryBean<?, ?> clientRegion = (ClientRegionFactoryBean<?, ?>) bean;
|
||||
|
||||
configureAsLocalClientRegion(environment, clientRegion);
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("unused")
|
||||
RegionConfigurer localClientRegionConfigurer(Environment environment) {
|
||||
|
||||
return new RegionConfigurer() {
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, ClientRegionFactoryBean<?, ?> bean) {
|
||||
configureAsLocalClientRegion(environment, bean);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected <K, V> ClientRegionFactoryBean configureAsLocalClientRegion(Environment environment,
|
||||
ClientRegionFactoryBean<K, V> clientRegion) {
|
||||
|
||||
ClientRegionShortcut shortcut =
|
||||
environment.getProperty(SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY,
|
||||
ClientRegionShortcut.class, LOCAL_CLIENT_REGION_SHORTCUT);
|
||||
|
||||
clientRegion.setPoolName(null);
|
||||
clientRegion.setShortcut(shortcut);
|
||||
|
||||
return clientRegion;
|
||||
}
|
||||
|
||||
static final class CusterNotAvailableCondition extends ClusterAwareConfiguration.ClusterAwareCondition {
|
||||
|
||||
@Override
|
||||
public synchronized boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
return !super.matches(context, metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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.geode.config.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The {@link EnableClusterAware} helps an Spring Boot application using Apache Geode (or Pivotal GemFire
|
||||
* / Pivotal Cloud Cache (PCC)) decide whether it needs to operate in {@literal local-only mode}
|
||||
* or {@literal client/server}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Annotation
|
||||
* @see java.lang.annotation.Documented
|
||||
* @see java.lang.annotation.Inherited
|
||||
* @see java.lang.annotation.Retention
|
||||
* @see java.lang.annotation.Target
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableClusterConfiguration
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import(ClusterAwareConfiguration.class)
|
||||
public @interface EnableClusterAware {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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 example.app.crm.service;
|
||||
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import example.app.crm.model.Customer;
|
||||
|
||||
/**
|
||||
* {@link CustomerService} is a Spring {@link Service @Service} class servicing {@link Customer Customers}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.cache.annotation.Cacheable
|
||||
* @see org.springframework.stereotype.Service
|
||||
* @see example.app.crm.model.Customer
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Service
|
||||
public class CustomerService {
|
||||
|
||||
@Cacheable("CustomersByName")
|
||||
public Customer findByName(String name) {
|
||||
return Customer.newCustomer(System.currentTimeMillis(), name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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.geode.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.admin.GemfireAdminOperations;
|
||||
import org.springframework.data.gemfire.config.admin.remote.RestHttpGemfireAdminTemplate;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnablePdx;
|
||||
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import example.app.crm.model.Customer;
|
||||
import example.app.crm.service.CustomerService;
|
||||
|
||||
/**
|
||||
* Integration Tests asserting the functionality and behavior of {@link EnableClusterAware}
|
||||
* and {@link ClusterAvailableConfiguration} when the Apache Geode (or Pivotal GemFire) cluster of servers is available.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.cache.annotation.Cacheable
|
||||
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions
|
||||
* @see org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport
|
||||
* @see org.springframework.geode.config.annotation.ClusterAvailableConfiguration
|
||||
* @see org.springframework.geode.config.annotation.EnableClusterAware
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(
|
||||
classes = ClusterAvailableConfigurationIntegrationTests.GeodeClientApplication.class,
|
||||
properties = { "spring.data.gemfire.management.use-http=false" },
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE
|
||||
)
|
||||
@SuppressWarnings("unused")
|
||||
public class ClusterAvailableConfigurationIntegrationTests extends ForkingClientServerIntegrationTestsSupport {
|
||||
|
||||
private static final String LOG_LEVEL = "error";
|
||||
|
||||
@BeforeClass
|
||||
public static void runGemFireServer() throws IOException {
|
||||
startGemFireServer(GeodeServerApplication.class);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ClientCache clientCache;
|
||||
|
||||
@Resource(name = "Customers")
|
||||
private Region<Long, Customer> customers;
|
||||
|
||||
@Resource(name = "CustomersByName")
|
||||
private Region<String, Customer> customersByName;
|
||||
|
||||
@Resource(name = "Example")
|
||||
private Region<Object, Object> example;
|
||||
|
||||
@Before
|
||||
public void assertRegionConfiguration() {
|
||||
|
||||
assertRegion(this.example, "Example", DataPolicy.EMPTY, "DEFAULT");
|
||||
assertRegion(this.customers, "Customers", DataPolicy.EMPTY, "DEFAULT");
|
||||
assertRegion(this.customersByName, "CustomersByName", DataPolicy.EMPTY, "DEFAULT");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void assertRegionConfigurationOnServers() {
|
||||
|
||||
GemfireAdminOperations adminOperations = new RestHttpGemfireAdminTemplate.Builder()
|
||||
.with(this.clientCache)
|
||||
.on("localhost")
|
||||
.listenOn(Integer.getInteger(GEMFIRE_CACHE_SERVER_PORT_PROPERTY, CacheServer.DEFAULT_PORT))
|
||||
.build();
|
||||
|
||||
assertThat(adminOperations).isNotNull();
|
||||
|
||||
assertThat(adminOperations.getAvailableServerRegions())
|
||||
.containsExactlyInAnyOrder("Customers", "CustomersByName", "Example");
|
||||
}
|
||||
|
||||
private void assertRegion(Region<?, ?> region, String name, DataPolicy dataPolicy, String poolName) {
|
||||
|
||||
assertThat(region).isNotNull();
|
||||
assertThat(region.getName()).isEqualTo(name);
|
||||
assertThat(region.getAttributes()).isNotNull();
|
||||
assertThat(region.getAttributes().getDataPolicy()).isEqualTo(dataPolicy);
|
||||
assertThat(region.getAttributes().getPoolName()).isEqualTo(poolName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customersRegionDataAccessOperationsWork() {
|
||||
|
||||
Customer jonDoe = Customer.newCustomer(1L, "Jon Doe");
|
||||
|
||||
assertThat(this.customers.put(jonDoe.getId(), jonDoe)).isNull();
|
||||
assertThat(this.customers.get(jonDoe.getId())).isEqualTo(jonDoe);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customersByNameRegionDataAccessOperationsWork() {
|
||||
|
||||
Customer jonDoe = Customer.newCustomer(2L, "Jane Doe");
|
||||
|
||||
assertThat(this.customersByName.put(jonDoe.getName(), jonDoe)).isNull();
|
||||
assertThat(this.customersByName.get(jonDoe.getName())).isEqualTo(jonDoe);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exampleRegionDataAccessOperationsWork() {
|
||||
|
||||
assertThat(this.example.put(1, "TEST")).isNull();
|
||||
assertThat(this.example.get(1)).isEqualTo("TEST");
|
||||
}
|
||||
|
||||
@CacheServerApplication(name = "ClusterAvailableConfigurationIntegrationTestsServer", logLevel = LOG_LEVEL)
|
||||
static class GeodeServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
AnnotationConfigApplicationContext applicationContext =
|
||||
new AnnotationConfigApplicationContext(GeodeServerApplication.class);
|
||||
|
||||
applicationContext.registerShutdownHook();
|
||||
}
|
||||
}
|
||||
|
||||
@EnableClusterAware
|
||||
@EnableCachingDefinedRegions
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
|
||||
@EnablePdx
|
||||
@ClientCacheApplication(name = "ClusterAvailableConfigurationIntegrationTests", logLevel = LOG_LEVEL)
|
||||
static class GeodeClientApplication {
|
||||
|
||||
@Bean("Example")
|
||||
ClientRegionFactoryBean<Object, Object> exampleRegion(GemFireCache cache) {
|
||||
|
||||
ClientRegionFactoryBean<Object, Object> exampleRegion = new ClientRegionFactoryBean<>();
|
||||
|
||||
exampleRegion.setCache(cache);
|
||||
exampleRegion.setShortcut(ClientRegionShortcut.PROXY);
|
||||
|
||||
return exampleRegion;
|
||||
}
|
||||
|
||||
@Bean
|
||||
CustomerService customerService() {
|
||||
return new CustomerService();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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.geode.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpointList;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link EnableClusterAware} and {@link ClusterAwareConfiguration}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.springframework.core.env.ConfigurableEnvironment
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.geode.config.annotation.ClusterAwareConfiguration
|
||||
* @see org.springframework.geode.config.annotation.EnableClusterAware
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class ClusterAwareConfigurationUnitTests extends IntegrationTestsSupport {
|
||||
|
||||
private ClusterAwareConfiguration.ClusterAwareCondition condition =
|
||||
spy(new ClusterAwareConfiguration.ClusterAwareCondition());
|
||||
|
||||
@Before @After
|
||||
public void setupAndTearDown() {
|
||||
System.clearProperty(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDefaultConnectionEndpointsIncludesDefaultLocatorAndDefaultServer() {
|
||||
|
||||
assertThat(this.condition.getDefaultConnectionEndpoints().stream()
|
||||
.map(ConnectionEndpoint::toString)
|
||||
.collect(Collectors.toList()))
|
||||
.containsExactly("localhost[40404]", "localhost[10334]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConfiguredConnectionEndpointsIsCorrect() {
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
MutablePropertySources propertySources = new MutablePropertySources();
|
||||
|
||||
Properties locatorProperties = new Properties();
|
||||
Properties serverProperties = new Properties();
|
||||
|
||||
locatorProperties.setProperty("spring.data.gemfire.pool.locators", "boombox[1234], cardboardbox[5678], mailbox[9012]");
|
||||
locatorProperties.setProperty("spring.data.gemfire.pool.car.locators", "skullbox[11235]");
|
||||
locatorProperties.setProperty("spring.data.gemfire.pool.other-property", "junk");
|
||||
serverProperties.setProperty("spring.data.gemfire.pool.servers", "mars[41414]");
|
||||
serverProperties.setProperty("spring.data.gemfire.pool.swimming.servers", "jupiter[42424], saturn[43434]");
|
||||
serverProperties.setProperty("spring.data.gemfire.pool.other-property", "junk");
|
||||
|
||||
propertySources.addLast(new PropertiesPropertySource("LocatorPoolProperties", locatorProperties));
|
||||
propertySources.addFirst(new PropertiesPropertySource("ServerPoolProperties", serverProperties));
|
||||
|
||||
when(mockEnvironment.getPropertySources()).thenReturn(propertySources);
|
||||
|
||||
when(mockEnvironment.getProperty(anyString())).thenAnswer(invocation -> {
|
||||
|
||||
String propertyName = invocation.getArgument(0);
|
||||
|
||||
return locatorProperties.getProperty(propertyName, serverProperties.getProperty(propertyName));
|
||||
});
|
||||
|
||||
List<ConnectionEndpoint> connectionEndpoints = this.condition.getConfiguredConnectionEndpoints(mockEnvironment);
|
||||
|
||||
List<String> connectionEndpointStrings = connectionEndpoints.stream()
|
||||
.map(ConnectionEndpoint::toString)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(connectionEndpoints).isNotNull();
|
||||
assertThat(connectionEndpoints).hasSize(7);
|
||||
assertThat(connectionEndpointStrings)
|
||||
.containsExactlyInAnyOrder("mars[41414]", "jupiter[42424]", "saturn[43434]", "boombox[1234]",
|
||||
"cardboardbox[5678]", "mailbox[9012]", "skullbox[11235]");
|
||||
|
||||
verify(mockEnvironment, times(1)).getPropertySources();
|
||||
verify(mockEnvironment, times(4)).getProperty(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void countConnectionsIsCorrect() throws Exception {
|
||||
|
||||
ConnectionEndpointList list = new ConnectionEndpointList(
|
||||
new ConnectionEndpoint("boombox", 1234),
|
||||
new ConnectionEndpoint("cardboardbox", 5678),
|
||||
new ConnectionEndpoint("mailbox", 9012),
|
||||
new ConnectionEndpoint("skullbox", 10334)
|
||||
);
|
||||
|
||||
Logger mockLogger = mock(Logger.class);
|
||||
|
||||
doReturn(mockLogger).when(this.condition).getLogger();
|
||||
|
||||
doAnswer(invocation -> {
|
||||
|
||||
ConnectionEndpoint connectionEndpoint = invocation.getArgument(0);
|
||||
|
||||
if (Arrays.asList("boombox", "skullbox").contains(connectionEndpoint.getHost())) {
|
||||
return mock(Socket.class);
|
||||
}
|
||||
else {
|
||||
throw new IOException("TEST");
|
||||
}
|
||||
|
||||
}).when(this.condition).connect(any(ConnectionEndpoint.class));
|
||||
|
||||
assertThat(this.condition.countConnections(list)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureTopologySetsLocalWhenConnectionCountIsLessThanOneAndEnvironmentDoesNotContainTargetProperty() {
|
||||
|
||||
assertThat(System.getProperties())
|
||||
.doesNotContainKey(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY);
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
ConnectionEndpointList connectionEndpoints =
|
||||
new ConnectionEndpointList(new ConnectionEndpoint("localhost", 1234));
|
||||
|
||||
this.condition.configureTopology(mockEnvironment, connectionEndpoints,0);
|
||||
|
||||
assertThat(System.getProperty(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY))
|
||||
.isEqualTo("LOCAL");
|
||||
|
||||
verify(mockEnvironment, times(1))
|
||||
.containsProperty(eq(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureTopologySetsClientServerWhenConnectionCountIsGreaterThanEqualToOne() {
|
||||
|
||||
assertThat(System.getProperties())
|
||||
.doesNotContainKey(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY);
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
this.condition.configureTopology(mockEnvironment, null,1);
|
||||
|
||||
assertThat(System.getProperties())
|
||||
.doesNotContainKey(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY);
|
||||
|
||||
verify(mockEnvironment, never())
|
||||
.containsProperty(eq(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureTopologySetsClientServerWhenEnvironmentContainsTargetProperty() {
|
||||
|
||||
assertThat(System.getProperties())
|
||||
.doesNotContainKey(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY);
|
||||
|
||||
ConfigurableEnvironment mockEnvironment = mock(ConfigurableEnvironment.class);
|
||||
|
||||
when(mockEnvironment.containsProperty(eq(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY)))
|
||||
.thenReturn(true);
|
||||
|
||||
this.condition.configureTopology(mockEnvironment, null,0);
|
||||
|
||||
assertThat(System.getProperties())
|
||||
.doesNotContainKey(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY);
|
||||
|
||||
verify(mockEnvironment, times(1))
|
||||
.containsProperty(eq(ClusterAwareConfiguration.SPRING_DATA_GEMFIRE_CACHE_CLIENT_REGION_SHORTCUT_PROPERTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isMatchReturnsTrue() {
|
||||
assertThat(this.condition.isMatch(null, 1)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotMatchReturnsFalse() {
|
||||
|
||||
ConnectionEndpointList connectionEndpoints =
|
||||
ConnectionEndpointList.from(new ConnectionEndpoint("localhost", 1234));
|
||||
|
||||
assertThat(this.condition.isMatch(connectionEndpoints, 0)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* https://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.geode.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
|
||||
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import example.app.crm.model.Customer;
|
||||
import example.app.crm.service.CustomerService;
|
||||
|
||||
/**
|
||||
* Integration Tests asserting the functionality and behavior of {@link EnableClusterAware}
|
||||
* and {@link ClusterNotAvailableConfiguration} when the Apache Geode (or Pivotal GemFire) cluster of servers
|
||||
* is not available.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.cache.annotation.Cacheable
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions
|
||||
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
|
||||
* @see org.springframework.geode.config.annotation.ClusterNotAvailableConfiguration
|
||||
* @see org.springframework.geode.config.annotation.EnableClusterAware
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class ClusterNotAvailableConfigurationIntegrationTests extends IntegrationTestsSupport {
|
||||
|
||||
private static final String LOG_LEVEL = "error";
|
||||
|
||||
@Resource(name = "Customers")
|
||||
private Region<Long, Customer> customers;
|
||||
|
||||
@Resource(name = "CustomersByName")
|
||||
private Region<String, Customer> customersByName;
|
||||
|
||||
@Resource(name = "Example")
|
||||
private Region<Object, Object> example;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
assertRegion(this.example, "Example", DataPolicy.NORMAL, null);
|
||||
assertRegion(this.customers, "Customers", DataPolicy.NORMAL, null);
|
||||
assertRegion(this.customersByName, "CustomersByName", DataPolicy.NORMAL, null);
|
||||
}
|
||||
|
||||
private void assertRegion(Region<?, ?> region, String name, DataPolicy dataPolicy, String poolName) {
|
||||
|
||||
assertThat(region).isNotNull();
|
||||
assertThat(region.getName()).isEqualTo(name);
|
||||
assertThat(region.getAttributes()).isNotNull();
|
||||
assertThat(region.getAttributes().getDataPolicy()).isEqualTo(dataPolicy);
|
||||
assertThat(region.getAttributes().getPoolName()).isEqualTo(poolName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customersRegionDataAccessOperationsWork() {
|
||||
|
||||
Customer jonDoe = Customer.newCustomer(1L, "Jon Doe");
|
||||
|
||||
assertThat(this.customers.put(jonDoe.getId(), jonDoe)).isNull();
|
||||
assertThat(this.customers.get(jonDoe.getId())).isEqualTo(jonDoe);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customersByNameRegionDataAccessOperationsWork() {
|
||||
|
||||
Customer jonDoe = Customer.newCustomer(2L, "Jane Doe");
|
||||
|
||||
assertThat(this.customersByName.put(jonDoe.getName(), jonDoe)).isNull();
|
||||
assertThat(this.customersByName.get(jonDoe.getName())).isEqualTo(jonDoe);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exampleRegionDataAccessOperationsWork() {
|
||||
|
||||
assertThat(this.example.put(1, "TEST")).isNull();
|
||||
assertThat(this.example.get(1)).isEqualTo("TEST");
|
||||
}
|
||||
|
||||
@EnableClusterAware
|
||||
@EnableCachingDefinedRegions
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
|
||||
@ClientCacheApplication(name = "ClusterAvailableConfigurationIntegrationTests", logLevel = LOG_LEVEL)
|
||||
static class GeodeClientApplication {
|
||||
|
||||
@Bean("Example")
|
||||
ClientRegionFactoryBean<Object, Object> exampleRegion(GemFireCache cache) {
|
||||
|
||||
ClientRegionFactoryBean<Object, Object> exampleRegion = new ClientRegionFactoryBean<>();
|
||||
|
||||
exampleRegion.setCache(cache);
|
||||
exampleRegion.setShortcut(ClientRegionShortcut.PROXY);
|
||||
|
||||
return exampleRegion;
|
||||
}
|
||||
|
||||
@Bean
|
||||
CustomerService customerService() {
|
||||
return new CustomerService();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user