SGF-222 - Configure and start GemFire Locators with SDG config.
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeIterable;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.apache.geode.distributed.Locator;
|
||||
import org.apache.geode.distributed.LocatorLauncher;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.gemfire.config.annotation.LocatorConfigurer;
|
||||
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link FactoryBean} used to configure and initialize (bootstrap) an Apache Geode or Pivotal GemFire
|
||||
* {@link Locator} using the {@link LocatorLauncher} class.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.distributed.Locator
|
||||
* @see org.apache.geode.distributed.LocatorLauncher
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorConfigurer
|
||||
* @see org.springframework.data.gemfire.support.AbstractFactoryBeanSupport
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LocatorFactoryBean extends AbstractFactoryBeanSupport<Locator> implements InitializingBean {
|
||||
|
||||
public static final int DEFAULT_PORT = 10334;
|
||||
|
||||
public static final String DEFAULT_LOG_LEVEL = "config";
|
||||
public static final String LOG_LEVEL_PROPERTY = "log-level";
|
||||
|
||||
private Integer port = DEFAULT_PORT;
|
||||
|
||||
private List<LocatorConfigurer> locatorConfigurers = new ArrayList<>();
|
||||
|
||||
private Locator locator;
|
||||
|
||||
private LocatorConfigurer compositeLocatorConfigurer = (beanName, bean) ->
|
||||
nullSafeList(this.locatorConfigurers).forEach(locatorConfigurer ->
|
||||
locatorConfigurer.configure(beanName, bean));
|
||||
|
||||
private LocatorLauncher locatorLauncher;
|
||||
|
||||
private Properties gemfireProperties;
|
||||
|
||||
private String bindAddress;
|
||||
private String hostnameForClients;
|
||||
private String logLevel;
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
applyLocatorConfigurers(getCompositeLocatorConfigurer());
|
||||
init();
|
||||
}
|
||||
|
||||
protected void applyLocatorConfigurers(LocatorConfigurer... locatorConfigurers) {
|
||||
applyLocatorConfigurers(Arrays.asList(nullSafeArray(locatorConfigurers, LocatorConfigurer.class)));
|
||||
}
|
||||
|
||||
protected void applyLocatorConfigurers(Iterable<LocatorConfigurer> locatorConfigurers) {
|
||||
StreamSupport.stream(nullSafeIterable(locatorConfigurers).spliterator(), false)
|
||||
.forEach(locatorConfigurer -> locatorConfigurer.configure(getBeanName(), this));
|
||||
}
|
||||
|
||||
public void init() {
|
||||
|
||||
LocatorLauncher.Builder locatorBuilder = configureGemfireProperties(newLocatorLauncherBuilder());
|
||||
|
||||
getBindAddress().ifPresent(locatorBuilder::setBindAddress);
|
||||
getHostnameForClients().ifPresent(locatorBuilder::setHostnameForClients);
|
||||
getName().ifPresent(locatorBuilder::setMemberName);
|
||||
|
||||
locatorBuilder.set(LOG_LEVEL_PROPERTY, getLogLevel());
|
||||
locatorBuilder.setPort(getPort());
|
||||
|
||||
locatorBuilder = postProcess(locatorBuilder);
|
||||
|
||||
this.locatorLauncher = postProcess(locatorBuilder.build());
|
||||
|
||||
LocatorLauncher.LocatorState locatorState = this.locatorLauncher.start();
|
||||
|
||||
/*
|
||||
if (LocatorLauncher.Status.ONLINE.equals(locatorState.getStatus())) {
|
||||
// log warning
|
||||
}
|
||||
*/
|
||||
|
||||
this.locator = this.locatorLauncher.getLocator();
|
||||
}
|
||||
|
||||
protected LocatorLauncher.Builder configureGemfireProperties(LocatorLauncher.Builder locatorBuilder) {
|
||||
|
||||
Properties gemfireProperties = getGemFireProperties();
|
||||
|
||||
gemfireProperties.stringPropertyNames().stream()
|
||||
.forEach(propertyName -> locatorBuilder.set(propertyName, gemfireProperties.getProperty(propertyName)));
|
||||
|
||||
return locatorBuilder;
|
||||
}
|
||||
|
||||
protected LocatorLauncher.Builder newLocatorLauncherBuilder() {
|
||||
return new LocatorLauncher.Builder();
|
||||
}
|
||||
|
||||
protected LocatorLauncher.Builder postProcess(LocatorLauncher.Builder locatorBuilder) {
|
||||
return locatorBuilder;
|
||||
}
|
||||
|
||||
protected LocatorLauncher postProcess(LocatorLauncher locatorLauncher) {
|
||||
return locatorLauncher;
|
||||
}
|
||||
|
||||
public Locator getLocator() {
|
||||
return this.locator;
|
||||
}
|
||||
|
||||
public LocatorLauncher getLocatorLauncher() {
|
||||
return this.locatorLauncher;
|
||||
}
|
||||
|
||||
@Nullable @Override
|
||||
public Locator getObject() throws Exception {
|
||||
|
||||
Locator locator = getLocator();
|
||||
|
||||
Assert.state(locator != null, "Locator was not configured and initialized");
|
||||
|
||||
return locator;
|
||||
}
|
||||
|
||||
@Nullable @Override
|
||||
public Class<?> getObjectType() {
|
||||
|
||||
Locator locator = getLocator();
|
||||
|
||||
return locator != null ? locator.getClass() : Locator.class;
|
||||
}
|
||||
|
||||
public void setBindAddress(String bindAddress) {
|
||||
this.bindAddress = bindAddress;
|
||||
}
|
||||
|
||||
public Optional<String> getBindAddress() {
|
||||
|
||||
return Optional.ofNullable(this.bindAddress)
|
||||
.filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
public LocatorConfigurer getCompositeLocatorConfigurer() {
|
||||
return this.compositeLocatorConfigurer;
|
||||
}
|
||||
|
||||
public void setGemFireProperties(Properties gemfireProperties) {
|
||||
this.gemfireProperties = gemfireProperties;
|
||||
}
|
||||
|
||||
public Properties getGemFireProperties() {
|
||||
|
||||
if (this.gemfireProperties == null) {
|
||||
this.gemfireProperties = new Properties();
|
||||
}
|
||||
|
||||
return this.gemfireProperties;
|
||||
}
|
||||
|
||||
public void setHostnameForClients(String hostnameForClients) {
|
||||
this.hostnameForClients = hostnameForClients;
|
||||
}
|
||||
|
||||
public Optional<String> getHostnameForClients() {
|
||||
|
||||
return Optional.ofNullable(this.hostnameForClients)
|
||||
.filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
public void setLocatorConfigurers(LocatorConfigurer... locatorConfigurers) {
|
||||
setLocatorConfigurers(Arrays.asList(nullSafeArray(locatorConfigurers, LocatorConfigurer.class)));
|
||||
}
|
||||
|
||||
public void setLocatorConfigurers(List<LocatorConfigurer> locatorConfigurers) {
|
||||
Optional.ofNullable(locatorConfigurers).ifPresent(this.locatorConfigurers::addAll);
|
||||
}
|
||||
|
||||
public void setLogLevel(String logLevel) {
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
public String getLogLevel() {
|
||||
return StringUtils.hasText(this.logLevel) ? this.logLevel : DEFAULT_LOG_LEVEL;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Optional<String> getName() {
|
||||
|
||||
return Optional.ofNullable(this.name)
|
||||
.filter(StringUtils::hasText);
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
|
||||
Assert.isTrue(port >= 0 && port < 65536, String.format("Network port [%d] is not valid", port));
|
||||
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return this.port;
|
||||
}
|
||||
}
|
||||
@@ -53,22 +53,24 @@ import org.springframework.context.annotation.Import;
|
||||
public @interface EnableLocator {
|
||||
|
||||
/**
|
||||
* Configures the host/IP address on which the embedded Locator service will bind to for accepting connections
|
||||
* from clients sending Locator requests.
|
||||
* Configures the host/IP address on which the embedded {@link Locator} service will bind to
|
||||
* for accepting connections from clients sending {@link Locator} requests.
|
||||
*
|
||||
* Defaults to {@literal localhost}.
|
||||
*
|
||||
* Use the {@literal spring.data.gemfire.locator.host} property in {@literal application.properties}.
|
||||
* Use the {@literal spring.data.gemfire.locator.host} property
|
||||
* in Spring Boot {@literal application.properties}.
|
||||
*/
|
||||
String host() default LocatorConfiguration.DEFAULT_HOST;
|
||||
|
||||
/**
|
||||
* Configures the port on which the embedded Locator service will bind to listening for client connections
|
||||
* sending Locator requests.
|
||||
* Configures the port on which the embedded {@link Locator} service will bind to
|
||||
* listening for client connections sending {@link Locator} requests.
|
||||
*
|
||||
* Defaults to {@literal 10334}.
|
||||
*
|
||||
* Use the {@literal spring.data.gemfire.locator.port} property in {@literal application.properties}.
|
||||
* Use the {@literal spring.data.gemfire.locator.port} property
|
||||
* in Spring Boot {@literal application.properties}.
|
||||
*/
|
||||
int port() default LocatorConfiguration.DEFAULT_LOCATOR_PORT;
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.lang.annotation.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.apache.geode.distributed.Locator;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The {@link LocatorApplication} {@link Annotation} enables a Spring Data for Apache Geode & Pivotal GemFire
|
||||
* application to become a {@link Locator} based application.
|
||||
*
|
||||
* @author John Blum
|
||||
* @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.Configuration
|
||||
* @see org.springframework.context.annotation.Import
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorApplicationConfiguration
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Configuration
|
||||
@Import(LocatorApplicationConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public @interface LocatorApplication {
|
||||
|
||||
/**
|
||||
* Configures the hostname or IP address on which the {@link Locator} will bind to for accepting connections
|
||||
* from clients sending {@link Locator} requests.
|
||||
*
|
||||
* Defaults to {@literal localhost}.
|
||||
*
|
||||
* Use the {@literal spring.data.gemfire.locator.bind-address} property
|
||||
* in Spring Boot {@literal application.properties}.
|
||||
*/
|
||||
String bindAddress() default "";
|
||||
|
||||
/**
|
||||
* Configures the {@link String hostname} used by clients connecting to this {@link Locator}.
|
||||
*
|
||||
* Defaults to {@literal localhost}.
|
||||
*
|
||||
* Use {@literal spring.data.gemfire.locator.hostname-for-clients}
|
||||
* in Spring Boot {@literal application.properties}.
|
||||
*/
|
||||
String hostnameForClients() default "";
|
||||
|
||||
/**
|
||||
* Configures the log level used to output log messages at Apache Geode / Pivotal GemFire {@link Locator} runtime.
|
||||
*
|
||||
* Defaults to {@literal config}.
|
||||
*
|
||||
* Use {@literal spring.data.gemfire.locator.log-level} property in {@literal application.properties}.
|
||||
*/
|
||||
String logLevel() default LocatorApplicationConfiguration.DEFAULT_LOG_LEVEL;
|
||||
|
||||
/**
|
||||
* Configures the name of the {@link Locator} application.
|
||||
*
|
||||
* Defaults to {@literal SpringBasedLocatorApplication}.
|
||||
*
|
||||
* Use the {@literal spring.data.gemfire.locator.name} property
|
||||
* in Spring Boot {@literal application.properties}.
|
||||
*/
|
||||
String name() default LocatorApplicationConfiguration.DEFAULT_NAME;
|
||||
|
||||
/**
|
||||
* Configures the port on which the embedded {@link Locator} service will bind to
|
||||
* listening for client connections sending {@link Locator} requests.
|
||||
*
|
||||
* Defaults to {@literal 10334}.
|
||||
*
|
||||
* Use the {@literal spring.data.gemfire.locator.port} property
|
||||
* in Spring Boot {@literal application.properties}.
|
||||
*/
|
||||
int port() default LocatorApplicationConfiguration.DEFAULT_PORT;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.distributed.Locator;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.LocatorFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link Configuration @Configuration} class used to configure and bootstrap an Apache Geode
|
||||
* or Pivotal GemFire {@link Locator}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.annotation.Annotation
|
||||
* @see org.apache.geode.distributed.Locator
|
||||
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.context.annotation.ImportAware
|
||||
* @see org.springframework.core.annotation.AnnotationAttributes
|
||||
* @see org.springframework.core.type.AnnotationMetadata
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.LocatorFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.ClientCacheFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorConfigurer
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
public class LocatorApplicationConfiguration extends AbstractAnnotationConfigSupport implements ImportAware {
|
||||
|
||||
public static final int DEFAULT_PORT = 10334;
|
||||
|
||||
public static final String DEFAULT_LOG_LEVEL = "config";
|
||||
public static final String DEFAULT_NAME = "SpringBasedLocatorApplication";
|
||||
|
||||
protected static final String EXCLUSIVE_LOCATOR_APPLICATION_ERROR_MESSAGE =
|
||||
"A Spring application cannot be both a Cache and a Locator application;"
|
||||
+ " You may annotate your Spring application main class with either 1 of"
|
||||
+ " [@ClientCacheApplication, @CacheServerApplication, @PeerCacheApplication] or @LocatorApplication;"
|
||||
+ " If you want to create a Spring, Apache Geode/Pivotal GemFire server application "
|
||||
+ " (i.e. [@PeerCacheApplication, @CacheServerApplication] and also run an embedded Locator service,"
|
||||
+ " then use @EnableLocator with 1 of the server-side, cache application annotations instead;"
|
||||
+ " Locators are not applicable to clients.";
|
||||
|
||||
private static final List<String> CACHE_FACTORY_BEAN_CLASS_NAMES =
|
||||
Arrays.asList(CacheFactoryBean.class.getName(), ClientCacheFactoryBean.class.getName());
|
||||
|
||||
private int port = DEFAULT_PORT;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<LocatorConfigurer> locatorConfigurers = Collections.emptyList();
|
||||
|
||||
private String bindAddress;
|
||||
private String hostnameForClients;
|
||||
private String logLevel;
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotationType() {
|
||||
return LocatorApplication.class;
|
||||
}
|
||||
|
||||
@Bean
|
||||
BeanFactoryPostProcessor exclusiveLocatorApplicationBeanFactoryPostProcessor() {
|
||||
|
||||
return configurableListableBeanFactory -> {
|
||||
|
||||
String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
|
||||
|
||||
boolean match = Arrays.stream(nullSafeArray(beanDefinitionNames, String.class))
|
||||
.map(configurableListableBeanFactory::getBeanDefinition)
|
||||
.anyMatch(beanDefinition ->
|
||||
|
||||
resolveBeanClassName(beanDefinition)
|
||||
.map(beanClassName -> {
|
||||
try {
|
||||
|
||||
Class<?> possibleCacheType =
|
||||
ClassUtils.resolveClassName(beanClassName, getBeanClassLoader());
|
||||
|
||||
return isCacheType(possibleCacheType);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return CACHE_FACTORY_BEAN_CLASS_NAMES.contains(beanClassName);
|
||||
}
|
||||
})
|
||||
.orElse(false));
|
||||
|
||||
if (match) {
|
||||
throw new BeanDefinitionStoreException(EXCLUSIVE_LOCATOR_APPLICATION_ERROR_MESSAGE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private boolean isCacheType(Class<?> type) {
|
||||
|
||||
return type != null
|
||||
&& (CacheFactoryBean.class.isAssignableFrom(type) || GemFireCache.class.isAssignableFrom(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
|
||||
if (isAnnotationPresent(importMetadata)) {
|
||||
|
||||
AnnotationAttributes locatorApplicationAnnotationAttributes = getAnnotationAttributes(importMetadata);
|
||||
|
||||
setBindAddress(resolveProperty(locatorProperty("bind-address"),
|
||||
locatorApplicationAnnotationAttributes.getString("bindAddress")));
|
||||
|
||||
setHostnameForClients(resolveProperty(locatorProperty("hostname-for-clients"),
|
||||
locatorApplicationAnnotationAttributes.getString("hostnameForClients")));
|
||||
|
||||
setLogLevel(resolveProperty(locatorProperty("log-level"),
|
||||
locatorApplicationAnnotationAttributes.getString("logLevel")));
|
||||
|
||||
setName(resolveProperty(locatorProperty("name"),
|
||||
locatorApplicationAnnotationAttributes.getString("name")));
|
||||
|
||||
setPort(resolveProperty(locatorProperty("port"),
|
||||
locatorApplicationAnnotationAttributes.<Integer>getNumber("port")));
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocatorFactoryBean locatorApplication() {
|
||||
|
||||
LocatorFactoryBean locatorFactoryBean = new LocatorFactoryBean();
|
||||
|
||||
locatorFactoryBean.setBindAddress(getBindAddress());
|
||||
locatorFactoryBean.setHostnameForClients(getHostnameForClients());
|
||||
locatorFactoryBean.setLocatorConfigurers(resolveLocatorConfigurers());
|
||||
locatorFactoryBean.setLogLevel(getLogLevel());
|
||||
locatorFactoryBean.setName(getName());
|
||||
locatorFactoryBean.setPort(getPort());
|
||||
|
||||
return locatorFactoryBean;
|
||||
}
|
||||
|
||||
private List<LocatorConfigurer> resolveLocatorConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.locatorConfigurers)
|
||||
.filter(locatorConfigurers -> !locatorConfigurers.isEmpty())
|
||||
.orElseGet(() ->
|
||||
|
||||
Optional.of(getBeanFactory())
|
||||
.filter(beanFactory -> beanFactory instanceof ListableBeanFactory)
|
||||
.map(beanFactory -> {
|
||||
|
||||
Map<String, LocatorConfigurer> beansOfType = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(LocatorConfigurer.class, true, false);
|
||||
|
||||
return nullSafeMap(beansOfType).values().stream()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
})
|
||||
.orElseGet(Collections::emptyList)
|
||||
);
|
||||
}
|
||||
|
||||
public void setBindAddress(String bindAddress) {
|
||||
this.bindAddress = bindAddress;
|
||||
}
|
||||
|
||||
public String getBindAddress() {
|
||||
return this.bindAddress;
|
||||
}
|
||||
|
||||
public void setHostnameForClients(String hostnameForClients) {
|
||||
this.hostnameForClients = hostnameForClients;
|
||||
}
|
||||
|
||||
public String getHostnameForClients() {
|
||||
return this.hostnameForClients;
|
||||
}
|
||||
|
||||
public void setLogLevel(String logLevel) {
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
public String getLogLevel() {
|
||||
return this.logLevel;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import org.apache.geode.distributed.Locator;
|
||||
import org.springframework.data.gemfire.LocatorFactoryBean;
|
||||
|
||||
/**
|
||||
* A Spring Configurer used to apply additional, customized configuration for an Apache Geode or Pivotal GemFire
|
||||
* {@link Locator}.
|
||||
*
|
||||
* This Configurer is particularly useful when using {@link LocatorApplication} annotation to configure and bootstrap
|
||||
* an Apache Geode or Pivotal GemFire {@link Locator}.
|
||||
*
|
||||
* This Configurer is NOT applied when configuring an enabling an embedded {@link Locator}
|
||||
* using SDG's {@link @EnableLocator} annotation.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.FunctionalInterface
|
||||
* @see org.apache.geode.distributed.Locator
|
||||
* @see org.springframework.data.gemfire.LocatorFactoryBean
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface LocatorConfigurer {
|
||||
|
||||
/**
|
||||
* Customizes the configuration of the {@link LocatorFactoryBean}.
|
||||
*
|
||||
* @param beanName {@link String name} of the bean in the Spring context.
|
||||
* @param bean {@link LocatorFactoryBean} used to configure and bootstrap an Apache Geode or Pivotal GemFire
|
||||
* {@link Locator} using Spring.
|
||||
* @see org.springframework.data.gemfire.LocatorFactoryBean
|
||||
*/
|
||||
void configure(String beanName, LocatorFactoryBean bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
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.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.distributed.Locator;
|
||||
import org.apache.geode.distributed.LocatorLauncher;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.data.gemfire.config.annotation.LocatorConfigurer;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link LocatorFactoryBean}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.apache.geode.distributed.Locator
|
||||
* @see org.apache.geode.distributed.LocatorLauncher
|
||||
* @see org.springframework.data.gemfire.LocatorFactoryBean
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorConfigurer
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class LocatorFactoryBeanUnitTests {
|
||||
|
||||
public LocatorFactoryBean locatorFactoryBean;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
this.locatorFactoryBean = spy(new LocatorFactoryBean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetCallsApplyLocatorConfigurersAndInit() throws Exception {
|
||||
|
||||
doNothing().when(this.locatorFactoryBean).applyLocatorConfigurers(any(LocatorConfigurer.class));
|
||||
doNothing().when(this.locatorFactoryBean).init();
|
||||
|
||||
this.locatorFactoryBean.afterPropertiesSet();
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(this.locatorFactoryBean);
|
||||
|
||||
inOrder.verify(this.locatorFactoryBean, times(1)).getCompositeLocatorConfigurer();
|
||||
inOrder.verify(this.locatorFactoryBean, times(1)).applyLocatorConfigurers(any(LocatorConfigurer.class));
|
||||
inOrder.verify(this.locatorFactoryBean, times(1)).init();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void appliesArrayOfLocatorConfigurersCallsIterableOfLocatorConfigurers() {
|
||||
|
||||
LocatorConfigurer mockLocatorConfigurerOne = mock(LocatorConfigurer.class);
|
||||
LocatorConfigurer mockLocatorConfigurerTwo = mock(LocatorConfigurer.class);
|
||||
|
||||
doCallRealMethod().when(this.locatorFactoryBean).applyLocatorConfigurers(any(LocatorConfigurer.class));
|
||||
|
||||
doAnswer(invocation -> {
|
||||
|
||||
Iterable<LocatorConfigurer> locatorConfigurers = invocation.getArgument(0, Iterable.class);
|
||||
|
||||
assertThat(locatorConfigurers).isNotNull();
|
||||
assertThat(locatorConfigurers).containsExactly(mockLocatorConfigurerOne, mockLocatorConfigurerTwo);
|
||||
|
||||
return null;
|
||||
|
||||
}).when(this.locatorFactoryBean).applyLocatorConfigurers(any(Iterable.class));
|
||||
|
||||
this.locatorFactoryBean.applyLocatorConfigurers(mockLocatorConfigurerOne, mockLocatorConfigurerTwo);
|
||||
|
||||
verify(this.locatorFactoryBean, times(1)).applyLocatorConfigurers(any(Iterable.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void appliesIterableOfLocatorConfigurersInvokesLocatorConfigurers() {
|
||||
|
||||
LocatorConfigurer mockLocatorConfigurerOne = mock(LocatorConfigurer.class);
|
||||
LocatorConfigurer mockLocatorConfigurerTwo = mock(LocatorConfigurer.class);
|
||||
|
||||
doCallRealMethod().when(this.locatorFactoryBean).applyLocatorConfigurers(any(Iterable.class));
|
||||
|
||||
this.locatorFactoryBean.setBeanName("TestLocator");
|
||||
this.locatorFactoryBean
|
||||
.applyLocatorConfigurers(Arrays.asList(mockLocatorConfigurerOne, mockLocatorConfigurerTwo));
|
||||
|
||||
verify(mockLocatorConfigurerOne, times(1))
|
||||
.configure(eq("TestLocator"), eq(this.locatorFactoryBean));
|
||||
|
||||
verify(mockLocatorConfigurerTwo, times(1))
|
||||
.configure(eq("TestLocator"), eq(this.locatorFactoryBean));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initBuildsLocator() throws Exception {
|
||||
|
||||
Locator mockLocator = mock(Locator.class);
|
||||
|
||||
LocatorLauncher mockLocatorLauncher = mock(LocatorLauncher.class);
|
||||
|
||||
LocatorLauncher.Builder locatorBuilderSpy = spy(new LocatorLauncher.Builder());
|
||||
|
||||
when(mockLocatorLauncher.getLocator()).thenReturn(mockLocator);
|
||||
when(locatorBuilderSpy.build()).thenReturn(mockLocatorLauncher);
|
||||
when(this.locatorFactoryBean.newLocatorLauncherBuilder()).thenReturn(locatorBuilderSpy);
|
||||
|
||||
String testBindAddress = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
this.locatorFactoryBean.setBeanName("TestLocatorBean");
|
||||
this.locatorFactoryBean.setBindAddress(testBindAddress);
|
||||
this.locatorFactoryBean.setHostnameForClients("skullbox");
|
||||
this.locatorFactoryBean.setName("TestMember");
|
||||
this.locatorFactoryBean.setPort(54321);
|
||||
this.locatorFactoryBean.init();
|
||||
|
||||
assertThat(this.locatorFactoryBean.getLocator()).isEqualTo(mockLocator);
|
||||
assertThat(this.locatorFactoryBean.getLocatorLauncher()).isEqualTo(mockLocatorLauncher);
|
||||
|
||||
verify(locatorBuilderSpy, times(1)).set(eq("log-level"), eq("config"));
|
||||
verify(locatorBuilderSpy, times(1)).setBindAddress(eq(testBindAddress));
|
||||
verify(locatorBuilderSpy, times(1)).setHostnameForClients(eq("skullbox"));
|
||||
verify(locatorBuilderSpy, times(1)).setMemberName(eq("TestMember"));
|
||||
verify(locatorBuilderSpy, times(1)).setPort(eq(54321));
|
||||
verify(this.locatorFactoryBean, times(1)).postProcess(eq(locatorBuilderSpy));
|
||||
verify(this.locatorFactoryBean, times(1)).postProcess(eq(mockLocatorLauncher));
|
||||
verify(mockLocatorLauncher, times(1)).start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuresLocatorLauncherBuilderGemFireProperties() {
|
||||
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", "TEST");
|
||||
gemfireProperties.setProperty("log-level", "config");
|
||||
gemfireProperties.setProperty("locators", "localhost[11235],skullbox[12480]");
|
||||
|
||||
LocatorLauncher.Builder locatorBuilderSpy = spy(new LocatorLauncher.Builder());
|
||||
|
||||
this.locatorFactoryBean.setGemFireProperties(gemfireProperties);
|
||||
this.locatorFactoryBean.configureGemfireProperties(locatorBuilderSpy);
|
||||
|
||||
gemfireProperties.stringPropertyNames().forEach(propertyName ->
|
||||
verify(locatorBuilderSpy, times(1))
|
||||
.set(eq(propertyName), eq(gemfireProperties.getProperty(propertyName))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectReturnsLocator() throws Exception {
|
||||
|
||||
Locator mockLocator = mock(Locator.class);
|
||||
|
||||
doReturn(mockLocator).when(this.locatorFactoryBean).getLocator();
|
||||
|
||||
assertThat(this.locatorFactoryBean.getObject()).isEqualTo(mockLocator);
|
||||
|
||||
verify(this.locatorFactoryBean, times(1)).getLocator();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getObjectThrowsIllegalStateException() throws Exception {
|
||||
|
||||
try {
|
||||
this.locatorFactoryBean.getObject();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Locator was not configured and initialized");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectTypeEqualsLocatorClass() {
|
||||
|
||||
assertThat(this.locatorFactoryBean.getObjectType()).isEqualTo(Locator.class);
|
||||
|
||||
verify(this.locatorFactoryBean, times(1)).getLocator();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectTypeIsALocatorType() {
|
||||
|
||||
Locator mockLocator = mock(Locator.class);
|
||||
|
||||
doReturn(mockLocator).when(this.locatorFactoryBean).getLocator();
|
||||
|
||||
Class<?> objectType = this.locatorFactoryBean.getObjectType();
|
||||
|
||||
assertThat(Locator.class).isAssignableFrom(objectType);
|
||||
assertThat(objectType).isEqualTo(mockLocator.getClass());
|
||||
|
||||
verify(this.locatorFactoryBean, times(1)).getLocator();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetBindAddress() {
|
||||
|
||||
this.locatorFactoryBean.setBindAddress("10.105.210.16");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getBindAddress().orElse(null)).isEqualTo("10.105.210.16");
|
||||
|
||||
this.locatorFactoryBean.setBindAddress(null);
|
||||
|
||||
assertThat(this.locatorFactoryBean.getBindAddress().orElse(null)).isNull();
|
||||
|
||||
this.locatorFactoryBean.setBindAddress(" ");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getBindAddress().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetGemFireProperties() {
|
||||
|
||||
Properties testGemFireProperties = new Properties();
|
||||
|
||||
testGemFireProperties.setProperty("testKey", "testValue");
|
||||
|
||||
this.locatorFactoryBean.setGemFireProperties(testGemFireProperties);
|
||||
|
||||
assertThat(this.locatorFactoryBean.getGemFireProperties()).isEqualTo(testGemFireProperties);
|
||||
|
||||
this.locatorFactoryBean.setGemFireProperties(null);
|
||||
|
||||
Properties actualGemFireProperties = this.locatorFactoryBean.getGemFireProperties();
|
||||
|
||||
assertThat(actualGemFireProperties).isNotNull();
|
||||
assertThat(actualGemFireProperties).isNotEqualTo(testGemFireProperties);
|
||||
assertThat(actualGemFireProperties).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetHostnameForClients() {
|
||||
|
||||
this.locatorFactoryBean.setHostnameForClients("skullbox");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getHostnameForClients().orElse(null)).isEqualTo("skullbox");
|
||||
|
||||
this.locatorFactoryBean.setHostnameForClients(null);
|
||||
|
||||
assertThat(this.locatorFactoryBean.getHostnameForClients().orElse(null)).isNull();
|
||||
|
||||
this.locatorFactoryBean.setHostnameForClients(" ");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getHostnameForClients().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setArrayOfLocatorConfigurersCallsListOfLocatorConfigurers() {
|
||||
|
||||
LocatorConfigurer mockLocatorConfigurerOne = mock(LocatorConfigurer.class);
|
||||
LocatorConfigurer mockLocatorConfigurerTwo = mock(LocatorConfigurer.class);
|
||||
|
||||
this.locatorFactoryBean.setLocatorConfigurers(mockLocatorConfigurerOne, mockLocatorConfigurerTwo);
|
||||
|
||||
List<LocatorConfigurer> locatorconfigurers = Arrays.asList(mockLocatorConfigurerOne, mockLocatorConfigurerTwo);
|
||||
|
||||
verify(this.locatorFactoryBean, times(1)).setLocatorConfigurers(eq(locatorconfigurers));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setListOfLocatorConfigurersAddsAll() {
|
||||
|
||||
LocatorConfigurer mockLocatorConfigurerOne = mock(LocatorConfigurer.class);
|
||||
LocatorConfigurer mockLocatorConfigurerTwo = mock(LocatorConfigurer.class);
|
||||
|
||||
List<LocatorConfigurer> locatorconfigurers = Arrays.asList(mockLocatorConfigurerOne, mockLocatorConfigurerTwo);
|
||||
|
||||
this.locatorFactoryBean.setLocatorConfigurers(locatorconfigurers);
|
||||
|
||||
LocatorConfigurer compositeLocatorConfigurer = this.locatorFactoryBean.getCompositeLocatorConfigurer();
|
||||
|
||||
assertThat(compositeLocatorConfigurer).isNotNull();
|
||||
|
||||
compositeLocatorConfigurer.configure("TestLocator", this.locatorFactoryBean);
|
||||
|
||||
verify(mockLocatorConfigurerOne, times(1))
|
||||
.configure(eq("TestLocator"), eq(this.locatorFactoryBean));
|
||||
|
||||
verify(mockLocatorConfigurerTwo, times(1))
|
||||
.configure(eq("TestLocator"), eq(this.locatorFactoryBean));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetLogLevel() {
|
||||
|
||||
this.locatorFactoryBean.setLogLevel("info");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getLogLevel()).isEqualTo("info");
|
||||
|
||||
this.locatorFactoryBean.setLogLevel(null);
|
||||
|
||||
assertThat(this.locatorFactoryBean.getLogLevel()).isEqualTo(LocatorFactoryBean.DEFAULT_LOG_LEVEL);
|
||||
|
||||
this.locatorFactoryBean.setLogLevel(" ");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getLogLevel()).isEqualTo(LocatorFactoryBean.DEFAULT_LOG_LEVEL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetName() {
|
||||
|
||||
this.locatorFactoryBean.setName("TestLocator");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getName().orElse(null)).isEqualTo("TestLocator");
|
||||
|
||||
this.locatorFactoryBean.setName(null);
|
||||
|
||||
assertThat(this.locatorFactoryBean.getName().orElse(null)).isNull();
|
||||
|
||||
this.locatorFactoryBean.setName(" ");
|
||||
|
||||
assertThat(this.locatorFactoryBean.getName().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPortToValidValue() {
|
||||
|
||||
this.locatorFactoryBean.setPort(54321);
|
||||
|
||||
assertThat(this.locatorFactoryBean.getPort()).isEqualTo(54321);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setPortToOverflowValue() {
|
||||
|
||||
try {
|
||||
this.locatorFactoryBean.setPort(65536);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Network port [65536] is not valid");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setPortToUnderflowValue() {
|
||||
|
||||
try {
|
||||
this.locatorFactoryBean.setPort(-1);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Network port [-1] is not valid");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Fail.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.distributed.Locator;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
|
||||
|
||||
/**
|
||||
* Integration Tests for {@link LocatorApplication} and {@link LocatorApplicationConfiguration} asserting that
|
||||
* {@link GemFireCache} and {@link Locator} instances are mutually exclusive.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.distributed.Locator
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorApplicationConfiguration
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
* @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LocatorApplicationCannotCoexistWithCacheApplicationIntegrationTests {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
|
||||
Optional.ofNullable(this.applicationContext)
|
||||
.ifPresent(ConfigurableApplicationContext::close);
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
|
||||
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
|
||||
applicationContext.register(annotatedClasses);
|
||||
applicationContext.registerShutdownHook();
|
||||
applicationContext.refresh();
|
||||
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
private void testCacheAndLocatorApplication(Class<?> testConfiguration) {
|
||||
|
||||
try {
|
||||
|
||||
this.applicationContext = newApplicationContext(testConfiguration);
|
||||
this.applicationContext.getBean(GemFireCache.class);
|
||||
this.applicationContext.getBean(Locator.class);
|
||||
|
||||
fail("Caches and Locators cannot coexist!");
|
||||
}
|
||||
catch (BeanDefinitionStoreException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage(LocatorApplicationConfiguration.EXCLUSIVE_LOCATOR_APPLICATION_ERROR_MESSAGE);
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionStoreException.class)
|
||||
public void clientCacheAndLocatorApplicationThrowsException() {
|
||||
testCacheAndLocatorApplication(ClientCacheAndLocatorTestConfiguration.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionStoreException.class)
|
||||
public void locatorAndPeerCacheApplicationThrowsException() {
|
||||
testCacheAndLocatorApplication(LocatorAndPeerCacheTestConfiguration.class);
|
||||
}
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@LocatorApplication(logLevel = GEMFIRE_LOG_LEVEL, port = 0)
|
||||
static class ClientCacheAndLocatorTestConfiguration {
|
||||
|
||||
@Bean
|
||||
ClientCache mockClientCache() {
|
||||
return mock(ClientCache.class);
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@LocatorApplication(logLevel = GEMFIRE_LOG_LEVEL, port = 0)
|
||||
@PeerCacheApplication(logLevel = GEMFIRE_LOG_LEVEL)
|
||||
static class LocatorAndPeerCacheTestConfiguration { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.LocatorFactoryBean;
|
||||
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration Tests for {@link LocatorApplication} and {@link LocatorConfigurer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorApplicationConfiguration
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorConfigurer
|
||||
* @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class LocatorApplicationConfigurerIntegrationTests {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private LocatorFactoryBean locatorFactoryBean;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("locatorConfigurerOne")
|
||||
private LocatorConfigurer locatorConfigurerOne;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("locatorConfigurerTwo")
|
||||
private LocatorConfigurer locatorConfigurerTwo;
|
||||
|
||||
@Test
|
||||
public void locatorConfigurersInvoked() {
|
||||
|
||||
assertThat(this.locatorFactoryBean).isNotNull();
|
||||
assertThat(this.locatorConfigurerOne).isNotNull();
|
||||
assertThat(this.locatorConfigurerTwo).isNotNull();
|
||||
|
||||
Arrays.asList(this.locatorConfigurerOne, this.locatorConfigurerTwo).forEach(locatorConfigurer ->
|
||||
verify(locatorConfigurer, times(1))
|
||||
.configure(eq("locatorApplication"), eq(this.locatorFactoryBean)));
|
||||
}
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@LocatorApplication(logLevel = GEMFIRE_LOG_LEVEL, port = 0)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
BeanPostProcessor locatorFactoryBeanPostProcessor() {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Nullable @Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof LocatorFactoryBean) {
|
||||
|
||||
LocatorFactoryBean locatorFactoryBean = spy((LocatorFactoryBean) bean);
|
||||
|
||||
doNothing().when(locatorFactoryBean).init();
|
||||
|
||||
bean = locatorFactoryBean;
|
||||
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
LocatorConfigurer locatorConfigurerOne() {
|
||||
return mock(LocatorConfigurer.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
LocatorConfigurer locatorConfigurerTwo() {
|
||||
return mock(LocatorConfigurer.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.CacheFactory;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.Locator;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.gemfire.GemfireUtils;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration Tests for {@link LocatorApplication} and {@link LocatorApplicationConfiguration} asserting that
|
||||
* an Apache Geode / Pivotal GemFire {@link Cache} application can connect to the {@link Locator} configured
|
||||
* and bootstrapped by {@link LocatorApplication}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.CacheFactory
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.distributed.Locator
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.LocatorApplicationConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class LocatorApplicationIntegrationTests {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private Locator locator;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
assertThat(this.locator).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gemfireCacheCanConnectToLocator() {
|
||||
|
||||
DistributedSystem distributedSystem = this.locator.getDistributedSystem();
|
||||
|
||||
assertThat(distributedSystem).isNotNull();
|
||||
|
||||
Properties distributedSystemProperties = distributedSystem.getProperties();
|
||||
|
||||
assertThat(distributedSystemProperties).isNotNull();
|
||||
|
||||
Cache peerCache = null;
|
||||
|
||||
try {
|
||||
peerCache = new CacheFactory()
|
||||
.set("name", LocatorApplicationIntegrationTests.class.getSimpleName())
|
||||
.set("bind-address", distributedSystemProperties.getProperty("bind-address"))
|
||||
.set("cache-xml-file", distributedSystemProperties.getProperty("cache-xml-file"))
|
||||
.set("jmx-manager", distributedSystemProperties.getProperty("jmx-manager"))
|
||||
.set("locators", distributedSystemProperties.getProperty("locators"))
|
||||
.set("log-file", distributedSystemProperties.getProperty("log-file"))
|
||||
.create();
|
||||
|
||||
assertThat(peerCache).isNotNull();
|
||||
assertThat(peerCache.getDistributedSystem()).isNotNull();
|
||||
assertThat(peerCache.getDistributedSystem().getProperties()).isNotNull();
|
||||
assertThat(peerCache.getDistributedSystem().getProperties().getProperty("locators"))
|
||||
.isEqualTo(distributedSystemProperties.getProperty("locators"));
|
||||
}
|
||||
finally {
|
||||
GemfireUtils.close(peerCache);
|
||||
}
|
||||
}
|
||||
|
||||
@LocatorApplication(
|
||||
name = "LocatorApplicationIntegrationTests",
|
||||
bindAddress = "localhost",
|
||||
logLevel = GEMFIRE_LOG_LEVEL,
|
||||
port = 0
|
||||
)
|
||||
static class TestConfiguration { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.distributed.Locator;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.data.gemfire.LocatorFactoryBean;
|
||||
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
|
||||
/**
|
||||
* Integration Tests for {@link LocatorApplication} and {@link LocatorApplicationConfiguration} asserting that
|
||||
* the {@link Locator} is configured with {@link Properties}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.distributed.Locator
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
* @see org.springframework.data.gemfire.LocatorFactoryBean
|
||||
* @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects
|
||||
* @see org.springframework.mock.env.MockPropertySource
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LocatorApplicationPropertiesIntegrationTests {
|
||||
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
|
||||
Optional.ofNullable(this.applicationContext)
|
||||
.ifPresent(ConfigurableApplicationContext::close);
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext newApplicationContext(PropertySource<?> testPropertySource,
|
||||
Class<?>... annotatedClasses) {
|
||||
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
|
||||
MutablePropertySources propertySources = applicationContext.getEnvironment().getPropertySources();
|
||||
|
||||
propertySources.addFirst(testPropertySource);
|
||||
|
||||
applicationContext.register(annotatedClasses);
|
||||
applicationContext.registerShutdownHook();
|
||||
applicationContext.refresh();
|
||||
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locatorIsConfiguredWithProperties() {
|
||||
|
||||
MockPropertySource testPropertySource = new MockPropertySource()
|
||||
.withProperty("spring.data.gemfire.locator.bind-address", "10.120.240.32")
|
||||
.withProperty("spring.data.gemfire.locator.hostname-for-clients", "skullbox")
|
||||
.withProperty("spring.data.gemfire.locator.log-level", "error")
|
||||
.withProperty("spring.data.gemfire.locator.name", "MockLocator")
|
||||
.withProperty("spring.data.gemfire.locator.port", 54321);
|
||||
|
||||
this.applicationContext = newApplicationContext(testPropertySource, TestConfiguration.class);
|
||||
|
||||
LocatorFactoryBean locatorFactoryBean = this.applicationContext.getBean(LocatorFactoryBean.class);
|
||||
|
||||
assertThat(locatorFactoryBean).isNotNull();
|
||||
assertThat(locatorFactoryBean.getBindAddress().orElse(null)).isEqualTo("10.120.240.32");
|
||||
assertThat(locatorFactoryBean.getHostnameForClients().orElse(null)).isEqualTo("skullbox");
|
||||
assertThat(locatorFactoryBean.getLogLevel()).isEqualTo("error");
|
||||
assertThat(locatorFactoryBean.getName().orElse(null)).isEqualTo("MockLocator");
|
||||
assertThat(locatorFactoryBean.getPort()).isEqualTo(54321);
|
||||
}
|
||||
|
||||
@EnableGemFireMockObjects
|
||||
@LocatorApplication(
|
||||
bindAddress = "10.105.210.16",
|
||||
hostnameForClients = "mailbox",
|
||||
logLevel = "info",
|
||||
name = "TestLocator",
|
||||
port = 12345
|
||||
)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
BeanPostProcessor locatorFactoryBeanPostProcessor() {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Nullable @Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof LocatorFactoryBean) {
|
||||
|
||||
LocatorFactoryBean locatorFactoryBean = spy((LocatorFactoryBean) bean);
|
||||
|
||||
doNothing().when(locatorFactoryBean).init();
|
||||
|
||||
bean = locatorFactoryBean;
|
||||
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user