Fixup documentation and samples.

This commit is contained in:
John Blum
2017-07-26 01:35:27 -07:00
parent e3cc3e7388
commit 04168ef1b3
28 changed files with 1110 additions and 1291 deletions

View File

@@ -19,11 +19,6 @@ dependencies {
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile seleniumDependencies
// testCompile 'org.seleniumhq.selenium:htmlunit-driver'
// testCompile 'org.seleniumhq.selenium:selenium-api'
// testCompile 'org.seleniumhq.selenium:selenium-java'
// testCompile 'org.seleniumhq.selenium:selenium-remote-driver'
// testCompile 'org.seleniumhq.selenium:selenium-support'
integrationTestCompile seleniumDependencies
@@ -45,7 +40,7 @@ task runGemFireServer() {
doLast {
ext.port = reservePort()
println "Starting GemFire Server on port [$port] ..."
println "Starting Apache Geode Server on port [$port] ..."
def out = new StringBuilder()
def err = new StringBuilder()
@@ -56,9 +51,7 @@ task runGemFireServer() {
'java', '-server', '-ea', '-classpath', classpath,
//"-Dgemfire.log-file=gemfire-server.log",
//"-Dgemfire.log-level=config",
"-Dspring-session-data-gemfire.cache.server.port=$port",
"-Dspring-session-data-gemfire.log.level="
+ System.getProperty('spring-session-data-gemfire.log.level', 'warning'),
"-Dspring.session.data.geode.cache.server.port=$port",
'sample.server.GemFireServer'
]
@@ -83,11 +76,10 @@ integrationTest {
systemProperties['server.port'] = port
//systemProperties['gemfire.log-file'] = "gemfire-client.log"
//systemProperties['gemfire.log-level'] = "config"
systemProperties['spring-session-data-gemfire.cache.server.port'] = runGemFireServer.port
systemProperties['spring-session-data-gemfire.log.level'] = System.getProperty("spring-session-data-gemfire.log.level", "warning")
systemProperties['spring.session.data.geode.cache.server.port'] = runGemFireServer.port
}
doLast {
println 'Stopping GemFire Server...'
println 'Stopping Apache Geode Server...'
runGemFireServer.process?.destroyForcibly()
}
}

View File

@@ -16,9 +16,6 @@
package sample.client;
import static java.util.Arrays.stream;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
@@ -26,44 +23,21 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.HttpSession;
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.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.management.membership.ClientMembership;
import org.apache.geode.management.membership.ClientMembershipEvent;
import org.apache.geode.management.membership.ClientMembershipListenerAdapter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -88,18 +62,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
* @since 1.2.1
*/
// tag::class[]
@SpringBootApplication
@Controller
@EnableGemFireHttpSession(poolName = "DEFAULT")// <1>
@SuppressWarnings("unused")
@SpringBootApplication // <1>
@Controller // <2>
public class Application {
static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(30);
static final CountDownLatch LATCH = new CountDownLatch(1);
static final String DEFAULT_GEMFIRE_LOG_LEVEL = "config";
static final String GEMFIRE_DEFAULT_POOL_NAME = "DEFAULT";
static final String INDEX_TEMPLATE_VIEW_NAME = "index";
static final String PING_RESPONSE = "PONG";
static final String REQUEST_COUNT_ATTRIBUTE_NAME = "requestCount";
@@ -108,197 +74,32 @@ public class Application {
SpringApplication.run(Application.class, args);
}
@Configuration
static class GemFireConfiguration {
@ClientCacheApplication(name = "SpringSessionDataGeodeClientBootSample", logLevel = "warning",
pingInterval = 5000L, readTimeout = 15000, retryAttempts = 1, subscriptionEnabled = true) // <3>
@EnableGemFireHttpSession(poolName = "DEFAULT") // <4>
static class ClientCacheConfiguration extends IntegrationTestConfiguration {
// Required to resolve property placeholders in Spring @Value annotations.
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Properties gemfireProperties() { // <2>
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
//gemfireProperties.setProperty("log-file", "gemfire-client.log");
gemfireProperties.setProperty("log-level", logLevel());
return gemfireProperties;
}
String applicationName() {
return "spring-session-data-gemfire-boot-sample.".concat(getClass().getSimpleName());
}
String logLevel() {
return System.getProperty("spring-session-data-gemfire.log.level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
ClientCacheFactoryBean gemfireCache(
@Value("${spring-session-data-gemfire.cache.server.host:localhost}") String host,
@Value("${spring-session-data-gemfire.cache.server.port:40404}") int port) { // <3>
ClientCacheConfigurer clientCacheServerPortConfigurer(
@Value("${spring.session.data.geode.cache.server.port:40404}") int port) { // <5>
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
// GemFire Pool settings <4>
gemfireCache.setKeepAlive(false);
gemfireCache.setPingInterval(TimeUnit.SECONDS.toMillis(5));
gemfireCache.setReadTimeout(intValue(TimeUnit.SECONDS.toMillis(15)));
gemfireCache.setRetryAttempts(1);
gemfireCache.setSubscriptionEnabled(true);
gemfireCache.setThreadLocalConnections(false);
gemfireCache.setServers(Collections.singletonList(newConnectionEndpoint(host, port)));
registerClientMembershipListener(); // <5>
return gemfireCache;
}
int intValue(Number number) {
return number.intValue();
}
ConnectionEndpoint newConnectionEndpoint(String host, int port) {
return new ConnectionEndpoint(host, port);
}
void registerClientMembershipListener() {
ClientMembership.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
@Override
public void memberJoined(ClientMembershipEvent event) {
LATCH.countDown();
}
});
}
@Bean(name = "Example")
@Profile("debug")
ClientRegionFactoryBean<String, Object> exampleRegion(ClientCache gemfireCache) {
ClientRegionFactoryBean<String, Object> exampleRegionFactory = new ClientRegionFactoryBean<>();
exampleRegionFactory.setCache(gemfireCache);
exampleRegionFactory.setClose(false);
exampleRegionFactory.setShortcut(ClientRegionShortcut.PROXY);
return exampleRegionFactory;
}
@Bean
BeanPostProcessor gemfireClientServerReadyBeanPostProcessor(
@Value("${spring-session-data-gemfire.cache.server.host:localhost}") final String host,
@Value("${spring-session-data-gemfire.cache.server.port:40404}") final int port) { // <5>
return new BeanPostProcessor() {
private final AtomicBoolean checkGemFireServerIsRunning = new AtomicBoolean(true);
private final AtomicReference<Pool> defaultPool = new AtomicReference<>(null);
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (shouldCheckWhetherGemFireServerIsRunning(bean, beanName)) {
try {
validateCacheClientNotified();
validateCacheClientSubscriptionQueueConnectionEstablished();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return bean;
}
private boolean shouldCheckWhetherGemFireServerIsRunning(Object bean, String beanName) {
return (isGemFireRegion(bean, beanName)
? checkGemFireServerIsRunning.compareAndSet(true, false)
: whenGemFireCache(bean, beanName));
}
private boolean isGemFireRegion(Object bean, String beanName) {
return (GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME.equals(beanName)
|| bean instanceof Region);
}
private boolean whenGemFireCache(Object bean, String beanName) {
if (bean instanceof ClientCache) {
defaultPool.compareAndSet(null, ((ClientCache) bean).getDefaultPool());
}
return false;
}
private void validateCacheClientNotified() throws InterruptedException {
boolean didNotTimeout = LATCH.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
Assert.state(didNotTimeout, String.format(
"GemFire Cache Server failed to start on host [%s] and port [%d]", host, port));
}
@SuppressWarnings("all")
private void validateCacheClientSubscriptionQueueConnectionEstablished() throws InterruptedException {
boolean cacheClientSubscriptionQueueConnectionEstablished = false;
Pool pool = defaultIfNull(this.defaultPool.get(), GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME,
GEMFIRE_DEFAULT_POOL_NAME);
if (pool instanceof PoolImpl) {
long timeout = (System.currentTimeMillis() + DEFAULT_TIMEOUT);
while (System.currentTimeMillis() < timeout
&& !((PoolImpl) pool).isPrimaryUpdaterAlive()) {
synchronized (pool) {
TimeUnit.MILLISECONDS.timedWait(pool, 500L);
}
}
cacheClientSubscriptionQueueConnectionEstablished |=
((PoolImpl) pool).isPrimaryUpdaterAlive();
}
Assert.state(cacheClientSubscriptionQueueConnectionEstablished, String.format(
"Cache client subscription queue connection not established; GemFire Pool was [%s];"
+ " GemFire Pool configuration was [locators = %s, servers = %s]",
pool, pool.getLocators(), pool.getServers()));
}
private Pool defaultIfNull(Pool pool, String... poolNames) {
AtomicReference<Pool> poolRef = new AtomicReference<>(null);
stream(nullSafeArray(poolNames, String.class)).forEach(poolName ->
poolRef.set(Optional.ofNullable(pool).orElseGet(() -> PoolManager.find(poolName))));
return poolRef.get();
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
};
return (beanName, cacheServerFactoryBean) ->
cacheServerFactoryBean.setServers(Collections.singletonList(
newConnectionEndpoint("localhost", port)));
}
}
@Configuration
static class SpringWebMvcConfiguration {
static class SpringWebMvcConfiguration { // <6>
@Bean
public WebMvcConfigurer webMvcConfig() { // <6>
public WebMvcConfigurer webMvcConfig() {
return new WebMvcConfigurer() {
@@ -310,9 +111,6 @@ public class Application {
}
}
@Autowired(required = false)
private ClientCache gemfireCache;
@ExceptionHandler
@ResponseBody
public String errorHandler(Throwable error) {
@@ -323,35 +121,22 @@ public class Application {
@RequestMapping(method = RequestMethod.GET, path = "/ping")
@ResponseBody
public String ping() { // <7>
public String ping() {
return PING_RESPONSE;
}
@RequestMapping(method = RequestMethod.GET, path = "/time")
@ResponseBody
public String time() {
return String.valueOf(this.gemfireCache.getRegion("/Example").get("time"));
}
/*
@RequestMapping("/")
public String index() { // <6>
return INDEX_TEMPLATE_VIEW_NAME;
}
*/
@RequestMapping(method = RequestMethod.POST, path = "/session")
public String session(HttpSession session, ModelMap modelMap,
@RequestParam(name = "attributeName", required = false) String name,
@RequestParam(name = "attributeValue", required = false) String value) { // <8>
@RequestParam(name = "attributeValue", required = false) String value) { // <7>
modelMap.addAttribute("sessionAttributes", attributes(setAttribute(updateRequestCount(session), name, value)));
modelMap.addAttribute("sessionAttributes",
attributes(setAttribute(updateRequestCount(session), name, value)));
return INDEX_TEMPLATE_VIEW_NAME;
}
// end::class[]
// end::class[]
/* (non-Javadoc) */
@SuppressWarnings("all")
HttpSession updateRequestCount(HttpSession session) {
@@ -362,17 +147,14 @@ public class Application {
}
}
/* (non-Javadoc) */
Integer nullSafeIncrement(Integer value) {
return (nullSafeIntValue(value) + 1);
}
/* (non-Javadoc) */
int nullSafeIntValue(Number value) {
return Optional.ofNullable(value).map(Number::intValue).orElse(0);
}
/* (non-Javadoc) */
HttpSession setAttribute(HttpSession session, String attributeName, String attributeValue) {
if (isSet(attributeName, attributeValue)) {
@@ -382,7 +164,6 @@ public class Application {
return session;
}
/* (non-Javadoc) */
boolean isSet(String... values) {
boolean set = true;
@@ -394,7 +175,6 @@ public class Application {
return set;
}
/* (non-Javadoc) */
Map<String, String> attributes(HttpSession session) {
Map<String, String> sessionAttributes = new HashMap<>();
@@ -406,7 +186,6 @@ public class Application {
return sessionAttributes;
}
/* (non-Javadoc) */
<T> Iterable<T> toIterable(Enumeration<T> enumeration) {
return () -> Optional.ofNullable(enumeration).map(CollectionUtils::toIterator)

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2017 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 sample.client;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.management.membership.ClientMembership;
import org.apache.geode.management.membership.ClientMembershipEvent;
import org.apache.geode.management.membership.ClientMembershipListenerAdapter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.util.Assert;
/**
* The IntegrationTestConfiguration class...
*
* @author John Blum
* @since 1.0.0
*/
public class IntegrationTestConfiguration {
static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
static final CountDownLatch LATCH = new CountDownLatch(1);
static final String GEMFIRE_DEFAULT_POOL_NAME = "DEFAULT";
@Bean
BeanPostProcessor clientServerReadyBeanPostProcessor(
@Value("${spring.session.data.geode.cache.server.port:40404}") int port) { // <5>
return new BeanPostProcessor() {
private final AtomicBoolean checkGemFireServerIsRunning = new AtomicBoolean(true);
private final AtomicReference<Pool> defaultPool = new AtomicReference<>(null);
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (shouldCheckWhetherGemFireServerIsRunning(bean, beanName)) {
try {
validateCacheClientNotified();
validateCacheClientSubscriptionQueueConnectionEstablished();
}
catch (InterruptedException cause) {
Thread.currentThread().interrupt();
}
}
return bean;
}
private boolean shouldCheckWhetherGemFireServerIsRunning(Object bean, String beanName) {
return (isGemFireRegion(bean, beanName)
? checkGemFireServerIsRunning.compareAndSet(true, false)
: whenGemFireCache(bean, beanName));
}
private boolean isGemFireRegion(Object bean, String beanName) {
return (GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME.equals(beanName)
|| bean instanceof Region);
}
private boolean whenGemFireCache(Object bean, String beanName) {
if (bean instanceof ClientCache) {
defaultPool.compareAndSet(null, ((ClientCache) bean).getDefaultPool());
}
return false;
}
private void validateCacheClientNotified() throws InterruptedException {
boolean didNotTimeout = LATCH.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
Assert.state(didNotTimeout, String.format(
"Apache Geode Cache Server failed to start on host [%s] and port [%d]", "localhost", port));
}
@SuppressWarnings("all")
private void validateCacheClientSubscriptionQueueConnectionEstablished() throws InterruptedException {
boolean cacheClientSubscriptionQueueConnectionEstablished = false;
Pool pool = defaultIfNull(this.defaultPool.get(), GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME,
GEMFIRE_DEFAULT_POOL_NAME);
if (pool instanceof PoolImpl) {
long timeout = (System.currentTimeMillis() + DEFAULT_TIMEOUT);
while (System.currentTimeMillis() < timeout && !((PoolImpl) pool).isPrimaryUpdaterAlive()) {
synchronized (pool) {
TimeUnit.MILLISECONDS.timedWait(pool, 500L);
}
}
cacheClientSubscriptionQueueConnectionEstablished |= ((PoolImpl) pool).isPrimaryUpdaterAlive();
}
Assert.state(cacheClientSubscriptionQueueConnectionEstablished,
String.format("Cache client subscription queue connection not established; Geode Pool was [%s];"
+ " Geode Pool configuration was [locators = %s, servers = %s]",
pool, pool.getLocators(), pool.getServers()));
}
private Pool defaultIfNull(Pool pool, String... poolNames) {
for (String poolName : poolNames) {
pool = (pool != null ? pool : PoolManager.find(poolName));
}
return pool;
}
};
}
ConnectionEndpoint newConnectionEndpoint(String host, int port) {
return new ConnectionEndpoint(host, port);
}
@Bean
ClientCacheConfigurer registerClientMembershipListener() {
return (beanName, bean) -> {
ClientMembership.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
@Override
public void memberJoined(ClientMembershipEvent event) {
LATCH.countDown();
}
});
};
}
}

View File

@@ -16,27 +16,15 @@
package sample.server;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
import org.springframework.data.gemfire.config.annotation.CacheServerConfigurer;
import org.springframework.data.gemfire.config.annotation.EnableManager;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
/**
@@ -51,103 +39,31 @@ import org.springframework.session.data.gemfire.config.annotation.web.http.Enabl
* @since 1.2.1
*/
// tag::class[]
@SpringBootApplication
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 20) // <1>
@SpringBootApplication // <1>
@CacheServerApplication(name = "SpringSessionDataGeodeServerBootSample", logLevel = "warning") // <2>
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 20) // <3>
@EnableManager(start = true) // <4>
@SuppressWarnings("unused")
public class GemFireServer {
static final String DEFAULT_GEMFIRE_LOG_LEVEL = "config";
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(GemFireServer.class);
springApplication.setWebApplicationType(WebApplicationType.NONE);
springApplication.run(args);
}
// Required to resolve property placeholders in Spring @Value annotations.
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Properties gemfireProperties() { // <2>
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
//gemfireProperties.setProperty("log-file", "gemfire-server.log");
gemfireProperties.setProperty("log-level", logLevel());
gemfireProperties.setProperty("jmx-manager", "true");
gemfireProperties.setProperty("jmx-manager-start", "true");
return gemfireProperties;
}
String applicationName() {
return "spring-session-data-gemfire-boot-sample:".concat(getClass().getSimpleName());
}
String logLevel() {
return System.getProperty("spring-session-data-gemfire.log.level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
CacheFactoryBean gemfireCache() { // <3>
CacheServerConfigurer cacheServerPortConfigurer(
@Value("${spring.session.data.geode.cache.server.port:40404}") int port) { // <5>
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean
CacheServerFactoryBean gemfireCacheServer(GemFireCache gemfireCache,
@Value("${spring-session-data-gemfire.cache.server.bind-address:localhost}") String bindAddress,
@Value("${spring-session-data-gemfire.cache.server.hostname-for-clients:localhost}") String hostnameForClients,
@Value("${spring-session-data-gemfire.cache.server.port:40404}") int port) { // <4>
CacheServerFactoryBean gemfireCacheServer = new CacheServerFactoryBean();
gemfireCacheServer.setAutoStartup(true);
gemfireCacheServer.setBindAddress(bindAddress);
gemfireCacheServer.setCache((Cache) gemfireCache);
gemfireCacheServer.setHostNameForClients(hostnameForClients);
gemfireCacheServer.setMaxTimeBetweenPings(Long.valueOf(TimeUnit.SECONDS.toMillis(60)).intValue());
gemfireCacheServer.setPort(port);
return gemfireCacheServer;
}
@Bean(name = "Example")
@Profile("debug")
ReplicatedRegionFactoryBean<String, Object> exampleRegion(GemFireCache gemfireCache) {
ReplicatedRegionFactoryBean<String, Object> exampleRegionFactory = new ReplicatedRegionFactoryBean<>();
exampleRegionFactory.setCache(gemfireCache);
exampleRegionFactory.setClose(false);
return exampleRegionFactory;
}
@Autowired
private GemFireCache gemfireCache;
@Bean
@Profile("debug")
CommandLineRunner exampleInitializer() {
return args -> {
Region<String, Object> example = this.gemfireCache.getRegion("/Example");
String key = "time";
example.put(key, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:ss a")));
System.err.printf("Example.get(%s) is [%s]%n", key, example.get(key));
};
return (beanName, cacheServerFactoryBean) ->
cacheServerFactoryBean.setPort(port);
}
}
// end::class[]

View File

@@ -76,6 +76,7 @@ public final class NativeGemFireServer implements Runnable {
}
private static void writeStringTo(File file, String fileContents) {
PrintWriter fileWriter = null;
try {
@@ -92,6 +93,7 @@ public final class NativeGemFireServer implements Runnable {
}
}
}
private NativeGemFireServer(String[] args) {
this.args = nullSafeStringArray(args);
}
@@ -122,11 +124,13 @@ public final class NativeGemFireServer implements Runnable {
}
private String applicationName(String applicationName) {
return StringUtils.hasText(applicationName) ? applicationName
: "spring-session-data-gemfire.boot.sample." + NativeGemFireServer.class.getSimpleName();
}
private Properties gemfireProperties(String applicationName) {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName);
@@ -143,6 +147,7 @@ public final class NativeGemFireServer implements Runnable {
}
private Cache createRegion(Cache gemfireCache) {
RegionFactory<Object, AbstractGemFireOperationsSessionRepository.GemFireSession> regionFactory =
gemfireCache.createRegionFactory(RegionShortcut.PARTITION);
@@ -162,6 +167,7 @@ public final class NativeGemFireServer implements Runnable {
}
private Cache addCacheServer(Cache gemfireCache) throws IOException {
CacheServer cacheServer = gemfireCache.addCacheServer();
cacheServer.setBindAddress(GEMFIRE_CACHE_SERVER_HOST);
@@ -173,6 +179,7 @@ public final class NativeGemFireServer implements Runnable {
}
private Cache registerShutdownHook(final Cache gemfireCache) {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
if (gemfireCache != null) {

View File

@@ -1,5 +1,6 @@
apply plugin: 'io.spring.convention.spring-sample-war'
apply plugin: "gemfire-server"
apply plugin: "application"
apply from: IDE_GRADLE
@@ -25,3 +26,5 @@ dependencies {
integrationTestRuntime "org.springframework.shell:spring-shell"
}
mainClassName = "sample.ServerConfig"

View File

@@ -17,200 +17,33 @@
package sample;
import java.util.Collections;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.management.membership.ClientMembership;
import org.apache.geode.management.membership.ClientMembershipEvent;
import org.apache.geode.management.membership.ClientMembershipListenerAdapter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.util.Assert;
// tag::class[]
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30, poolName = "DEFAULT") // <1>
public class ClientConfig {
static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
static final CountDownLatch LATCH = new CountDownLatch(1);
static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
static final String GEMFIRE_DEFAULT_POOL_NAME = "DEFAULT";
static final String PROXY_HOST = "dummy.example.com";
static final String PROXY_PORT = "3128";
@ClientCacheApplication(name = "SpringSessionDataGeodeClientJavaConfigSample", logLevel = "warning",
pingInterval = 5000L, readTimeout = 15000, retryAttempts = 1, subscriptionEnabled = true) // <1>
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30, poolName = "DEFAULT") // <2>
public class ClientConfig extends IntegrationTestConfig {
// Required to resolve property placeholders in Spring @Value annotations.
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Properties gemfireProperties() { // <2>
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
// gemfireProperties.setProperty("log-file", "gemfire-client.log");
gemfireProperties.setProperty("log-level", logLevel());
return gemfireProperties;
}
String applicationName() {
return "spring-session-data-gemfire-clientserver-javaconfig-sample:".concat(getClass().getSimpleName());
}
String logLevel() {
return System.getProperty("spring.session.data.gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
ClientCacheFactoryBean gemfireCache(
@Value("${spring.session.data.gemfire.host:" + ServerConfig.SERVER_HOST + "}") String host,
@Value("${spring.session.data.gemfire.port:" + ServerConfig.SERVER_PORT + "}") int port) { // <3>
ClientCacheConfigurer clientCacheServerPortConfigurer(
@Value("${spring.session.data.geode.cache.server.port:40404}") int port) { // <3>
ClientCacheFactoryBean clientCacheFactory = new ClientCacheFactoryBean();
clientCacheFactory.setClose(true);
clientCacheFactory.setProperties(gemfireProperties());
// GemFire Pool settings <4>
clientCacheFactory.setKeepAlive(false);
clientCacheFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
clientCacheFactory.setReadTimeout(intValue(TimeUnit.SECONDS.toMillis(15)));
clientCacheFactory.setRetryAttempts(1);
clientCacheFactory.setSubscriptionEnabled(true);
clientCacheFactory.setThreadLocalConnections(false);
clientCacheFactory.setServers(Collections.singletonList(newConnectionEndpoint(host, port)));
registerClientMembershipListener(); // <5>
return clientCacheFactory;
return (beanName, clientCacheFactoryBean) ->
clientCacheFactoryBean.setServers(Collections.singletonList(
newConnectionEndpoint("localhost", port)));
}
int intValue(Number number) {
return number.intValue();
}
ConnectionEndpoint newConnectionEndpoint(String host, int port) {
return new ConnectionEndpoint(host, port);
}
void registerClientMembershipListener() {
ClientMembership.registerClientMembershipListener(
new ClientMembershipListenerAdapter() {
@Override
public void memberJoined(ClientMembershipEvent event) {
LATCH.countDown();
}
});
}
@Bean
BeanPostProcessor gemfireClientServerReadyBeanPostProcessor(
@Value("${spring-session-data-gemfire.cache.server.host:localhost}") final String host,
@Value("${spring-session-data-gemfire.cache.server.port:12480}") final int port) { // <5>
return new BeanPostProcessor() {
private final AtomicBoolean checkGemFireServerIsRunning = new AtomicBoolean(true);
private final AtomicReference<Pool> defaultPool = new AtomicReference<Pool>(null);
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (shouldCheckWhetherGemFireServerIsRunning(bean, beanName)) {
try {
validateCacheClientNotified();
validateCacheClientSubscriptionQueueConnectionEstablished();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return bean;
}
private boolean shouldCheckWhetherGemFireServerIsRunning(Object bean, String beanName) {
return (isGemFireRegion(bean, beanName)
? checkGemFireServerIsRunning.compareAndSet(true, false)
: whenGemFireCache(bean, beanName));
}
private boolean isGemFireRegion(Object bean, String beanName) {
return (GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME.equals(beanName)
|| bean instanceof Region);
}
private boolean whenGemFireCache(Object bean, String beanName) {
if (bean instanceof ClientCache) {
defaultPool.compareAndSet(null, ((ClientCache) bean).getDefaultPool());
}
return false;
}
private void validateCacheClientNotified() throws InterruptedException {
boolean didNotTimeout = LATCH.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
Assert.state(didNotTimeout, String.format(
"GemFire Cache Server failed to start on host [%s] and port [%d]", host, port));
}
@SuppressWarnings("all")
private void validateCacheClientSubscriptionQueueConnectionEstablished() throws InterruptedException {
boolean cacheClientSubscriptionQueueConnectionEstablished = false;
Pool pool = defaultIfNull(this.defaultPool.get(), GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME,
GEMFIRE_DEFAULT_POOL_NAME);
if (pool instanceof PoolImpl) {
long timeout = (System.currentTimeMillis() + DEFAULT_TIMEOUT);
while (System.currentTimeMillis() < timeout
&& !((PoolImpl) pool).isPrimaryUpdaterAlive()) {
synchronized (pool) {
TimeUnit.MILLISECONDS.timedWait(pool, 500L);
}
}
cacheClientSubscriptionQueueConnectionEstablished |=
((PoolImpl) pool).isPrimaryUpdaterAlive();
}
Assert.state(cacheClientSubscriptionQueueConnectionEstablished, String.format(
"Cache client subscription queue connection not established; GemFire Pool was [%s];"
+ " GemFire Pool configuration was [locators = %s, servers = %s]",
pool, pool.getLocators(), pool.getServers()));
}
private Pool defaultIfNull(Pool pool, String... poolNames) {
for (String poolName : poolNames) {
pool = (pool != null ? pool : PoolManager.find(poolName));
}
return pool;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
};
}
// end::class[]
}
// end::class[]

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2017 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 sample;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.management.membership.ClientMembership;
import org.apache.geode.management.membership.ClientMembershipEvent;
import org.apache.geode.management.membership.ClientMembershipListenerAdapter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.util.Assert;
/**
* The IntegrationTestConfig class...
*
* @author John Blum
* @since 1.0.0
*/
public abstract class IntegrationTestConfig {
static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
static final CountDownLatch LATCH = new CountDownLatch(1);
static final String GEMFIRE_DEFAULT_POOL_NAME = "DEFAULT";
@Bean
BeanPostProcessor clientServerReadyBeanPostProcessor(
@Value("${spring.session.data.geode.cache.server.port:40404}") int port) { // <5>
return new BeanPostProcessor() {
private final AtomicBoolean checkGemFireServerIsRunning = new AtomicBoolean(true);
private final AtomicReference<Pool> defaultPool = new AtomicReference<>(null);
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (shouldCheckWhetherGemFireServerIsRunning(bean, beanName)) {
try {
validateCacheClientNotified();
validateCacheClientSubscriptionQueueConnectionEstablished();
}
catch (InterruptedException cause) {
Thread.currentThread().interrupt();
}
}
return bean;
}
private boolean shouldCheckWhetherGemFireServerIsRunning(Object bean, String beanName) {
return (isGemFireRegion(bean, beanName)
? checkGemFireServerIsRunning.compareAndSet(true, false)
: whenGemFireCache(bean, beanName));
}
private boolean isGemFireRegion(Object bean, String beanName) {
return (GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME.equals(beanName)
|| bean instanceof Region);
}
private boolean whenGemFireCache(Object bean, String beanName) {
if (bean instanceof ClientCache) {
defaultPool.compareAndSet(null, ((ClientCache) bean).getDefaultPool());
}
return false;
}
private void validateCacheClientNotified() throws InterruptedException {
boolean didNotTimeout = LATCH.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
Assert.state(didNotTimeout, String.format(
"Apache Geode Cache Server failed to start on host [%s] and port [%d]", "localhost", port));
}
@SuppressWarnings("all")
private void validateCacheClientSubscriptionQueueConnectionEstablished() throws InterruptedException {
boolean cacheClientSubscriptionQueueConnectionEstablished = false;
Pool pool = defaultIfNull(this.defaultPool.get(), GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME,
GEMFIRE_DEFAULT_POOL_NAME);
if (pool instanceof PoolImpl) {
long timeout = (System.currentTimeMillis() + DEFAULT_TIMEOUT);
while (System.currentTimeMillis() < timeout && !((PoolImpl) pool).isPrimaryUpdaterAlive()) {
synchronized (pool) {
TimeUnit.MILLISECONDS.timedWait(pool, 500L);
}
}
cacheClientSubscriptionQueueConnectionEstablished |= ((PoolImpl) pool).isPrimaryUpdaterAlive();
}
Assert.state(cacheClientSubscriptionQueueConnectionEstablished,
String.format("Cache client subscription queue connection not established; Geode Pool was [%s];"
+ " Geode Pool configuration was [locators = %s, servers = %s]",
pool, pool.getLocators(), pool.getServers()));
}
private Pool defaultIfNull(Pool pool, String... poolNames) {
for (String poolName : poolNames) {
pool = (pool != null ? pool : PoolManager.find(poolName));
}
return pool;
}
};
}
ConnectionEndpoint newConnectionEndpoint(String host, int port) {
return new ConnectionEndpoint(host, port);
}
@Bean
ClientCacheConfigurer registerClientMembershipListener() {
return (beanName, bean) -> {
ClientMembership.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
@Override
public void memberJoined(ClientMembershipEvent event) {
LATCH.countDown();
}
});
};
}
}

View File

@@ -17,86 +17,38 @@
package sample;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.GemFireCache;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
import org.springframework.data.gemfire.config.annotation.CacheServerConfigurer;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
// tag::class[]
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30) // <1>
@CacheServerApplication(name = "SpringSessionSampleJavaConfigGemFireClientServer", logLevel = "warning") // <1>
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30) // <2>
public class ServerConfig {
static final int SERVER_PORT = 12480;
static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
static final String SERVER_HOST = "localhost";
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException { // <5>
public static void main(String[] args) throws IOException {
new AnnotationConfigApplicationContext(ServerConfig.class).registerShutdownHook();
}
// Required to resolve property placeholders in Spring @Value annotations.
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Properties gemfireProperties() { // <2>
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
gemfireProperties.setProperty("mcast-port", "0");
// gemfireProperties.setProperty("log-file", "gemfire-server.log");
gemfireProperties.setProperty("log-level", logLevel());
// gemfireProperties.setProperty("jmx-manager", "true");
// gemfireProperties.setProperty("jmx-manager-start", "true");
return gemfireProperties;
}
String applicationName() {
return "samples:httpsession-gemfire-clientserver:".concat(getClass().getSimpleName());
}
String logLevel() {
return System.getProperty("sample.httpsession.gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
CacheFactoryBean gemfireCache() { // <3>
CacheServerConfigurer cacheServerPortConfigurer(
@Value("${spring.session.data.geode.cache.server.port:40404}") int port) { // <3>
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean
CacheServerFactoryBean gemfireCacheServer(GemFireCache gemfireCache,
@Value("${spring.session.data.gemfire.port:" + SERVER_PORT + "}") int port) { // <4>
CacheServerFactoryBean gemfireCacheServer = new CacheServerFactoryBean();
gemfireCacheServer.setAutoStartup(true);
gemfireCacheServer.setBindAddress(SERVER_HOST);
gemfireCacheServer.setCache((Cache) gemfireCache);
gemfireCacheServer.setHostNameForClients(SERVER_HOST);
gemfireCacheServer.setMaxTimeBetweenPings(Long.valueOf(TimeUnit.SECONDS.toMillis(60)).intValue());
gemfireCacheServer.setPort(port);
return gemfireCacheServer;
return (beanName, cacheServerFactoryBean) -> {
cacheServerFactoryBean.setPort(port);
};
}
}
// end::class[]

View File

@@ -28,15 +28,17 @@ import javax.servlet.http.HttpServletResponse;
@WebServlet("/session")
public class SessionServlet extends HttpServlet {
private static final long serialVersionUID = 2878267318695777395L;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String attributeName = request.getParameter("attributeName");
String attributeValue = request.getParameter("attributeValue");
request.getSession().setAttribute(attributeName, attributeValue);
response.sendRedirect(request.getContextPath() + "/");
}
private static final long serialVersionUID = 2878267318695777395L;
}
// tag::end[]

View File

@@ -16,38 +16,15 @@
package sample;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.config.annotation.EnableManager;
import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
// tag::class[]
@EnableGemFireHttpSession // <1>
@PeerCacheApplication(name = "SpringSessionSampleJavaConfigGemFireP2p", logLevel = "warning") // <1>
@EnableGemFireHttpSession // <2>
@EnableManager(start = true) // <3>
public class Config {
@Bean
Properties gemfireProperties() { // <2>
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", "GemFireP2PHttpSessionSample");
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level",
System.getProperty("sample.httpsession.gemfire.log-level", "warning"));
gemfireProperties.setProperty("jmx-manager", "true");
gemfireProperties.setProperty("jmx-manager-start", "true");
return gemfireProperties;
}
@Bean
CacheFactoryBean gemfireCache() { // <3>
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
}
// end::class[]

View File

@@ -28,15 +28,17 @@ import javax.servlet.http.HttpServletResponse;
@WebServlet("/session")
public class SessionServlet extends HttpServlet {
private static final long serialVersionUID = 2878267318695777395L;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String attributeName = request.getParameter("attributeName");
String attributeValue = request.getParameter("attributeValue");
request.getSession().setAttribute(attributeName, attributeValue);
response.sendRedirect(request.getContextPath() + "/");
}
private static final long serialVersionUID = 2878267318695777395L;
}
// tag::end[]

View File

@@ -1,5 +1,6 @@
apply plugin: 'io.spring.convention.spring-sample-war'
apply plugin: "gemfire-server"
apply plugin: "application"
apply from: IDE_GRADLE
@@ -25,3 +26,5 @@ dependencies {
integrationTestRuntime "org.springframework.shell:spring-shell"
}
mainClassName = "sample.ServerConfig"

View File

@@ -36,7 +36,7 @@ import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.util.Assert;
public class GemFireClientServerReadyBeanPostProcessor implements BeanPostProcessor {
public class ClientServerReadyBeanPostProcessor implements BeanPostProcessor {
private static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
@@ -55,16 +55,17 @@ public class GemFireClientServerReadyBeanPostProcessor implements BeanPostProces
);
}
@Value("${spring.session.data.gemfire.port:${application.gemfire.client-server.port}}")
@Value("${spring.session.data.geode.cache.server.port:${application.geode.client-server.port:40404}}")
private int port;
@Value("${application.gemfire.client-server.host:localhost}")
@Value("${application.geode.client-server.host:localhost}")
private String host;
private final AtomicBoolean checkGemFireServerIsRunning = new AtomicBoolean(true);
private final AtomicReference<Pool> gemfirePool = new AtomicReference<Pool>(null);
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (shouldCheckWhetherGemFireServerIsRunning(bean, beanName)) {
try {
validateCacheClientNotified();
@@ -79,17 +80,20 @@ public class GemFireClientServerReadyBeanPostProcessor implements BeanPostProces
}
private boolean shouldCheckWhetherGemFireServerIsRunning(Object bean, String beanName) {
return (isGemFireRegion(bean, beanName)
? this.checkGemFireServerIsRunning.compareAndSet(true, false)
: whenGemFirePool(bean, beanName));
}
private boolean isGemFireRegion(Object bean, String beanName) {
return (GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME.equals(beanName)
|| bean instanceof Region);
}
private boolean whenGemFirePool(Object bean, String beanName) {
if (bean instanceof Pool) {
this.gemfirePool.compareAndSet(null, (Pool) bean);
}
@@ -98,24 +102,26 @@ public class GemFireClientServerReadyBeanPostProcessor implements BeanPostProces
}
private void validateCacheClientNotified() throws InterruptedException {
boolean didNotTimeout = LATCH.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
Assert.state(didNotTimeout, String.format(
"GemFire Cache Server failed to start on host [%s] and port [%d]", this.host, this.port));
"Apache Geode Cache Server failed to start on host [%s] and port [%d]", this.host, this.port));
}
@SuppressWarnings("all")
private void validateCacheClientSubscriptionQueueConnectionEstablished() throws InterruptedException {
boolean cacheClientSubscriptionQueueConnectionEstablished = false;
Pool pool = defaultIfNull(this.gemfirePool.get(),
GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME, GEMFIRE_DEFAULT_POOL_NAME);
if (pool instanceof PoolImpl) {
long timeout = (System.currentTimeMillis() + DEFAULT_TIMEOUT);
while (System.currentTimeMillis() < timeout
&& !((PoolImpl) pool).isPrimaryUpdaterAlive()) {
while (System.currentTimeMillis() < timeout && !((PoolImpl) pool).isPrimaryUpdaterAlive()) {
synchronized (pool) {
TimeUnit.MILLISECONDS.timedWait(pool, 500L);
@@ -127,13 +133,14 @@ public class GemFireClientServerReadyBeanPostProcessor implements BeanPostProces
((PoolImpl) pool).isPrimaryUpdaterAlive();
}
Assert.state(cacheClientSubscriptionQueueConnectionEstablished, String.format(
"Cache client subscription queue connection not established; GemFire Pool was [%s];"
+ " GemFire Pool configuration was [locators = %s, servers = %s]",
Assert.state(cacheClientSubscriptionQueueConnectionEstablished,
String.format("Cache client subscription queue connection not established; Geode Pool was [%s];"
+ " Geode Pool configuration was [locators = %s, servers = %s]",
pool, pool.getLocators(), pool.getServers()));
}
private Pool defaultIfNull(Pool pool, String... poolNames) {
for (String poolName : poolNames) {
pool = (pool != null ? pool : PoolManager.find(poolName));
}
@@ -145,4 +152,3 @@ public class GemFireClientServerReadyBeanPostProcessor implements BeanPostProces
return bean;
}
}
// tag::end[]

View File

@@ -20,7 +20,6 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@SuppressWarnings("resource")
// tag::class[]
@Configuration // <1>
@ImportResource("META-INF/spring/session-server.xml") // <2>

View File

@@ -1,2 +1,2 @@
application.gemfire.client-server.host=localhost
application.gemfire.client-server.port=40404
application.geode.client-server.host=localhost
application.geode.client-server.port=40404

View File

@@ -13,17 +13,13 @@
">
<!-- tag::beans[] -->
<!--1-->
<context:annotation-config/>
<!--2-->
<context:property-placeholder location="classpath:META-INF/spring/application.properties"/>
<!--3-->
<!--1-->
<util:properties id="gemfireProperties">
<prop key="name">GemFireClientServerHttpSessionXmlSample</prop>
<prop key="mcast-port">0</prop>
<!--<prop key="log-file">gemfire-server.log</prop>-->
<prop key="name">SpringSessionSampleXmlGemFireClientServer</prop>
<prop key="log-level">${spring.session.data.gemfire.log-level:warning}</prop>
<!--
<prop key="jmx-manager">true</prop>
@@ -31,16 +27,16 @@
-->
</util:properties>
<!--4-->
<!--2-->
<gfe:cache properties-ref="gemfireProperties"/>
<!--5-->
<!--3-->
<gfe:cache-server auto-startup="true"
bind-address="${application.gemfire.client-server.host:localhost}"
host-name-for-clients="${application.gemfire.client-server.host:localhost}"
port="${spring.session.data.gemfire.port:${application.gemfire.client-server.port:40404}}"/>
bind-address="${application.geode.client-server.host:localhost}"
host-name-for-clients="${application.geode.client-server.host:localhost}"
port="${spring.session.data.geode.cache.server.port:${application.geode.client-server.port:40404}}"/>
<!--6-->
<!--4-->
<bean class="org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration"
p:maxInactiveIntervalInSeconds="30"/>
<!-- end::beans[] -->

View File

@@ -13,36 +13,27 @@
">
<!-- tag::beans[] -->
<!--1-->
<context:annotation-config/>
<!--2-->
<context:property-placeholder location="classpath:META-INF/spring/application.properties"/>
<!--3-->
<bean class="sample.GemFireClientServerReadyBeanPostProcessor"/>
<bean class="sample.ClientServerReadyBeanPostProcessor"/>
<!--4-->
<!--1-->
<util:properties id="gemfireProperties">
<!--<prop key="log-file">gemfire-client.log</prop>-->
<prop key="log-level">${spring.session.data.gemfire.log-level:warning}</prop>
<prop key="log-level">${spring.session.data.geode.log-level:warning}</prop>
</util:properties>
<!--5-->
<!--2-->
<gfe:client-cache properties-ref="gemfireProperties" pool-name="gemfirePool"/>
<!--6-->
<gfe:pool keep-alive="false"
ping-interval="5000"
read-timeout="15000"
retry-attempts="1"
subscription-enabled="true"
thread-local-connections="false">
<gfe:server host="${application.gemfire.client-server.host}"
port="${spring.session.data.gemfire.port:${application.gemfire.client-server.port}}"/>
<!--3-->
<gfe:pool ping-interval="5000" read-timeout="15000" retry-attempts="1" subscription-enabled="true">
<gfe:server host="${application.geode.client-server.host}"
port="${spring.session.data.geode.cache.server.port:${application.geode.client-server.port:40404}}"/>
</gfe:pool>
<!--7-->
<!--4-->
<bean class="org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration"
p:maxInactiveIntervalInSeconds="30" p:poolName="DEFAULT"/>
<!-- end::beans[] -->

View File

@@ -26,15 +26,17 @@ import javax.servlet.http.HttpServletResponse;
// tag::class[]
public class SessionServlet extends HttpServlet {
private static final long serialVersionUID = 2878267318695777395L;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String attributeName = request.getParameter("attributeName");
String attributeValue = request.getParameter("attributeValue");
request.getSession().setAttribute(attributeName, attributeValue);
response.sendRedirect(request.getContextPath() + "/");
}
private static final long serialVersionUID = 2878267318695777395L;
}
// end::class[]

View File

@@ -12,23 +12,23 @@
">
<!-- tag::beans[] -->
<!--1-->
<context:annotation-config/>
<context:property-placeholder/>
<bean class="org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration"/>
<!--2-->
<!--1-->
<util:properties id="gemfireProperties">
<prop key="name">GemFireP2PHttpSessionXmlSample</prop>
<prop key="mcast-port">0</prop>
<prop key="log-level">${sample.httpsession.gemfire.log-level:warning}</prop>
<prop key="name">SpringSessionSampleXmlGemFireP2p</prop>
<prop key="log-level">${spring.session.data.geode.log-level:warning}</prop>
<prop key="jmx-manager">true</prop>
<prop key="jmx-manager-start">true</prop>
</util:properties>
<!--3-->
<!--2-->
<gfe:cache properties-ref="gemfireProperties" use-bean-factory-locator="false"/>
<!--3-->
<bean class="org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration"/>
<!-- end::beans[] -->
</beans>