Add integration test to assert that no Spring (Session Data GemFire/Geode) artifacts of any kind are need on the classpath of a GemFire/Geode Server when PDX Serialization is used.
Resolves Issue #2.
This commit is contained in:
@@ -23,9 +23,12 @@ import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -50,6 +53,7 @@ import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.support.GemFireUtils;
|
||||
import org.springframework.session.events.AbstractSessionEvent;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link AbstractGemFireIntegrationTests} is an abstract base class encapsulating common functionality
|
||||
@@ -85,7 +89,7 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
protected static final String DEFAULT_PROCESS_CONTROL_FILENAME = "process.ctl";
|
||||
|
||||
protected static final String GEMFIRE_LOG_FILE_NAME =
|
||||
System.getProperty("spring.session.data.gemfire.log-file", "server.log");
|
||||
System.getProperty("spring.session.data.gemfire.log-file", "gemfire-server.log");
|
||||
|
||||
protected static final String GEMFIRE_LOG_LEVEL =
|
||||
System.getProperty("spring.session.data.gemfire.log-level", "error");
|
||||
@@ -101,13 +105,50 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
System.setProperty("gemfire.Query.VERBOSE", String.valueOf(isQueryDebuggingEnabled()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static String buildClassPathContainingJarFiles(String... jarFilenames) {
|
||||
|
||||
StringBuilder classpath = new StringBuilder();
|
||||
|
||||
stream(nullSafeArray(jarFilenames, String.class)).map(AbstractGemFireIntegrationTests::findJarInClasspath)
|
||||
.forEach(classpathEntry -> classpathEntry.filter(StringUtils::hasText).ifPresent(it -> {
|
||||
|
||||
if (classpath.length() > 0) {
|
||||
classpath.append(File.pathSeparator);
|
||||
}
|
||||
|
||||
classpath.append(it);
|
||||
}));
|
||||
|
||||
return classpath.toString();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private static Optional<URL> findClassInFileSystem(Class<?> type) {
|
||||
|
||||
return Optional.ofNullable(type)
|
||||
.map(AbstractGemFireIntegrationTests::getResourceName)
|
||||
.map(resourceName -> type.getClassLoader().getResource(resourceName));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private static Optional<String> findJarInClasspath(String jarFilename) {
|
||||
return stream(nullSafeArray(System.getProperty("java.class.path").split(File.pathSeparator), String.class))
|
||||
.filter(element -> element.contains(jarFilename)).findFirst();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private static String getResourceName(Class<?> type) {
|
||||
return type.getName().replaceAll("\\.", "/").concat(".class");
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static File createDirectory(String pathname) {
|
||||
|
||||
File directory = new File(WORKING_DIRECTORY, pathname);
|
||||
|
||||
assertThat(directory.isDirectory() || directory.mkdirs())
|
||||
.as(String.format("Failed to create directory (%1$s)", directory)).isTrue();
|
||||
.as(String.format("Failed to create directory [%s]", directory)).isTrue();
|
||||
|
||||
directory.deleteOnExit();
|
||||
|
||||
@@ -116,11 +157,15 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static List<String> createJavaProcessCommandLine(Class<?> type, String... args) {
|
||||
return createJavaProcessCommandLine(System.getProperty("java.class.path"), type, args);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static List<String> createJavaProcessCommandLine(String classpath, Class<?> type, String... args) {
|
||||
|
||||
List<String> commandLine = new ArrayList<>();
|
||||
|
||||
String javaHome = System.getProperty("java.home");
|
||||
|
||||
String javaExe = new File(new File(javaHome, "bin"), "java").getAbsolutePath();
|
||||
|
||||
commandLine.add(javaExe);
|
||||
@@ -131,28 +176,67 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
commandLine.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
|
||||
commandLine.addAll(extractJvmArguments(args));
|
||||
commandLine.add("-classpath");
|
||||
commandLine.add(System.getProperty("java.class.path"));
|
||||
commandLine.add(classpath);
|
||||
commandLine.add(type.getName());
|
||||
commandLine.addAll(extractProgramArguments(args));
|
||||
|
||||
// System.err.printf("Java process command-line is (%1$s)%n", commandLine);
|
||||
//System.err.printf("Java process command-line is [%s]%n", commandLine);
|
||||
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static List<String> extractJvmArguments(String... args) {
|
||||
private static List<String> extractJvmArguments(String... args) {
|
||||
return stream(args).filter(arg -> arg.startsWith("-")).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static List<String> extractProgramArguments(String... args) {
|
||||
private static List<String> extractProgramArguments(String... args) {
|
||||
return stream(args).filter(arg -> !arg.startsWith("-")).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
// Run Java Class in Directory with Arguments
|
||||
protected static String resolveClasspath(String classpath, Class<?> type) {
|
||||
|
||||
return Optional.ofNullable(classpath)
|
||||
.filter(StringUtils::hasText)
|
||||
.filter(it -> type != null)
|
||||
.flatMap(it -> findClassInFileSystem(type))
|
||||
.map(url -> {
|
||||
try {
|
||||
return new File(url.toURI());
|
||||
}
|
||||
catch (URISyntaxException ignore) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.map(File::getAbsolutePath)
|
||||
.map(pathname -> {
|
||||
|
||||
int indexOfTypeName = pathname.indexOf(getResourceName(type));
|
||||
|
||||
pathname = (indexOfTypeName > -1 ? pathname.substring(0, indexOfTypeName) : pathname);
|
||||
pathname = (pathname.endsWith(File.separator) ? pathname.substring(0, pathname.length() - 1) : pathname);
|
||||
|
||||
return pathname;
|
||||
})
|
||||
.map(location -> classpath.concat(File.pathSeparator).concat(location))
|
||||
.orElse(classpath);
|
||||
}
|
||||
|
||||
// Run Java Class in Directory with Arguments
|
||||
protected static Process run(Class<?> type, File directory, String... args) throws IOException {
|
||||
return new ProcessBuilder().command(createJavaProcessCommandLine(type, args)).directory(directory).start();
|
||||
return run(createJavaProcessCommandLine(type, args), directory);
|
||||
}
|
||||
|
||||
// Run Java Class using Classpath in Directory with Arguments
|
||||
protected static Process run(String classpath, Class<?> type, File directory, String... args) throws IOException {
|
||||
return run(createJavaProcessCommandLine(resolveClasspath(classpath, type), type, args), directory);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private static Process run(List<String> command, File directory) throws IOException {
|
||||
return new ProcessBuilder().command(command).directory(directory).inheritIO().redirectErrorStream(true).start();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -188,9 +272,9 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
if (!connected.get()) {
|
||||
if (!this.connected.get()) {
|
||||
socket = new Socket(host, port);
|
||||
connected.set(true);
|
||||
this.connected.set(true);
|
||||
}
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
@@ -214,7 +298,9 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static boolean waitForClientCacheToClose(long duration) {
|
||||
|
||||
try {
|
||||
|
||||
ClientCache clientCache = ClientCacheFactory.getAnyInstance();
|
||||
|
||||
clientCache.close();
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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 org.springframework.session.data.gemfire.serialization.pdx;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests;
|
||||
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession;
|
||||
import org.springframework.session.data.gemfire.GemFireOperationsSessionRepository;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
|
||||
import org.springframework.session.data.gemfire.server.GemFireServer;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* Integration tests asserting that a GemFire/Geode Server does not require any Spring Session Data GemFire/Geode
|
||||
* dependencies or any transitive dependencies when PDX serialization is in effect.
|
||||
*
|
||||
* /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/bin/java -server -ea
|
||||
* -Dgemfire.log-level=FINEST -Dgemfire.Query.VERBOSE=false -Dspring.session.data.gemfire.cache.server.port=34095
|
||||
* -classpath /Users/jblum/.gradle/caches/modules-2/files-2.1/antlr/antlr/2.7.7/83cd2cd674a217ade95a4bb83a8a14f351f48bd0/antlr-2.7.7.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/commons-collections/commons-collections/3.2.2/8ad72fe39fa8c91eaaf12aadb21e0c3661fe26d5/commons-collections-3.2.2.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.5/2852e6e05fbb95076fc091f6d1780f1f8fe35e0f/commons-io-2.5.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/commons-lang/commons-lang/2.6/ce1edb914c94ebc388f086c6827e8bdeec71ac2/commons-lang-2.6.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/io.github.lukehutch/fast-classpath-scanner/2.0.11/ae34a7a5e6de8ad1f86e12f6f7ae1869fcfe9987/fast-classpath-scanner-2.0.11.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/it.unimi.dsi/fastutil/7.1.0/9835253257524c1be7ab50c057aa2d418fb72082/fastutil-7.1.0.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/javax.resource/javax.resource-api/1.7/ae40e0864eb1e92c48bf82a2a3399cbbf523fb79/javax.resource-api-1.7.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/javax.transaction/javax.transaction-api/1.2/d81aff979d603edd90dcd8db2abc1f4ce6479e3e/javax.transaction-api-1.2.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/net.java.dev.jna/jna/4.5.0/55b548d3195efc5280bf1c3f17b49659c54dee40/jna-4.5.0.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.9.1/7a2999229464e7a324aa503c0a52ec0f05efe7bd/log4j-api-2.9.1.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-core/2.9.1/c041978c686866ee8534f538c6220238db3bb6be/log4j-core-2.9.1.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.apache.geode/geode-common/1.2.1/9db253081d33f424f6e3ce0cde4b306e23e3420b/geode-common-1.2.1.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.apache.geode/geode-core/1.2.1/fe853317e33dd2a1c291f29cee3c4be549f75a69/geode-core-1.2.1.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.apache.geode/geode-json/1.2.1/bdb4c262e4ce6bb3b22e0f511cfb133a65fa0c04/geode-json-1.2.1.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.9.1/60077fe98b11e4e7cf8af9b20609326a166d6ac4/jackson-core-2.9.1.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.jgroups/jgroups/3.6.10.Final/fc0ff5a8a9de27ab62939956f705c2909bf86bc2/jgroups-3.6.10.Final.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.apache.lucene/lucene-core/6.4.1/2a18924b9e0ed86b318902cb475a0b9ca4d7be5b/lucene-core-6.4.1.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.apache.shiro/shiro-core/1.4.0/6d05bd17e057fc12d278bb367c27f9cb0f3dc197/shiro-core-1.4.0.jar
|
||||
* :/Users/jblum/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.25/da76ca59f6a57ee3102f8f9bd9cee742973efa8a/slf4j-api-1.7.25.jar
|
||||
* :spring-session-data-geode/build/classes/integrationTest
|
||||
* org.springframework.session.data.gemfire.server.GemFireServer
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer
|
||||
* @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class SessionSerializationWithPdxRequiresNoServerConfigurationIntegrationTests
|
||||
extends AbstractGemFireIntegrationTests {
|
||||
|
||||
private static final DateFormat TIMESTAMP = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
|
||||
private static File processWorkingDirectory;
|
||||
|
||||
private static Process gemfireServer;
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = "error";
|
||||
|
||||
@Autowired
|
||||
private GemFireOperationsSessionRepository sessionRepository;
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
|
||||
System.err.printf("Starting a GemFire Server running on host [localhost] listening on port [%d]%n", port);
|
||||
|
||||
System.setProperty("spring.session.data.gemfire.cache.server.port", String.valueOf(port));
|
||||
|
||||
String classpath = buildClassPathContainingJarFiles("javax.transaction-api", "antlr",
|
||||
"commons-lang", "fastutil", "log4j-api", "log4j-core", "geode-common", "geode-core", "jgroups",
|
||||
"shiro-core", "slf4j-api");
|
||||
|
||||
String processWorkingDirectoryPathname =
|
||||
String.format("gemfire-server-pdx-serialization-tests-%1$s", TIMESTAMP.format(new Date()));
|
||||
|
||||
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
|
||||
|
||||
gemfireServer = run(classpath, GemFireServer.class,
|
||||
processWorkingDirectory, String.format("-Dspring.session.data.gemfire.cache.server.port=%d", port),
|
||||
String.format("-Dgemfire.log-level=%s", GEMFIRE_LOG_LEVEL));
|
||||
|
||||
assertThat(waitForCacheServerToStart("localhost", port)).isTrue();
|
||||
|
||||
System.err.printf("GemFire Server [startup time = %d ms]%n", System.currentTimeMillis() - t0);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopGemFireServer() {
|
||||
|
||||
Optional.ofNullable(gemfireServer).ifPresent(server -> {
|
||||
|
||||
server.destroy();
|
||||
|
||||
System.err.printf("GemFire Server [exit code = %d]%n",
|
||||
waitForProcessToStop(server, processWorkingDirectory));
|
||||
});
|
||||
|
||||
if (Boolean.valueOf(System.getProperty("spring.session.data.gemfire.fork.clean", Boolean.TRUE.toString()))) {
|
||||
FileSystemUtils.deleteRecursively(processWorkingDirectory);
|
||||
}
|
||||
|
||||
assertThat(waitForClientCacheToClose(DEFAULT_WAIT_DURATION)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionOperationsIsSuccessful() {
|
||||
|
||||
Session session = save(createSession("jonDoe"));
|
||||
|
||||
assertThat(session).isInstanceOf(GemFireSession.class);
|
||||
assertThat(session.getId()).isNotNull();
|
||||
assertThat(session.getCreationTime()).isBeforeOrEqualTo(Instant.now());
|
||||
assertThat(session.isExpired()).isFalse();
|
||||
assertThat(((GemFireSession) session).getPrincipalName()).isEqualTo("jonDoe");
|
||||
|
||||
Session sessionById = get(session.getId());
|
||||
|
||||
assertThat(sessionById).isEqualTo(session);
|
||||
assertThat(sessionById.isExpired()).isFalse();
|
||||
|
||||
Map<String, Session> sessionsByPrincipalName = this.sessionRepository.findByIndexNameAndIndexValue(
|
||||
GemFireOperationsSessionRepository.PRINCIPAL_NAME_INDEX_NAME, "jonDoe");
|
||||
|
||||
assertThat(sessionsByPrincipalName).hasSize(1);
|
||||
|
||||
Session sessionByPrincipalName = sessionsByPrincipalName.values().iterator().next();
|
||||
|
||||
assertThat(sessionByPrincipalName).isInstanceOf(GemFireSession.class);
|
||||
assertThat(sessionByPrincipalName).isEqualTo(session);
|
||||
assertThat(sessionByPrincipalName.isExpired()).isFalse();
|
||||
assertThat(((GemFireSession) sessionByPrincipalName).getPrincipalName()).isEqualTo("jonDoe");
|
||||
}
|
||||
|
||||
@ClientCacheApplication(logLevel = GEMFIRE_LOG_LEVEL, subscriptionEnabled = true)
|
||||
@EnableGemFireHttpSession(poolName = "DEFAULT")
|
||||
static class GemFireCacheClientConfiguration {
|
||||
|
||||
@Bean
|
||||
static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheConfigurer clientCachePoolPortConfigurer(
|
||||
@Value("${spring.session.data.gemfire.cache.server.port:" + CacheServer.DEFAULT_PORT + "}") int cacheServerPort) {
|
||||
|
||||
return (beanName, clientCacheFactoryBean) -> clientCacheFactoryBean.setServers(Collections.singletonList(
|
||||
new ConnectionEndpoint("localhost", cacheServerPort)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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 org.springframework.session.data.gemfire.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.CacheFactory;
|
||||
import org.apache.geode.cache.ExpirationAction;
|
||||
import org.apache.geode.cache.ExpirationAttributes;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionFactory;
|
||||
import org.apache.geode.cache.RegionShortcut;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
|
||||
/**
|
||||
* The {@link GemFireServer} class is a Java application class used to launch a GemFire Server
|
||||
* with a peer {@link Cache}, a {@link CacheServer} and the {@literal ClusteredSpringSessions}
|
||||
* {@link RegionShortcut#PARTITION} {@link Region}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class GemFireServer implements Runnable {
|
||||
|
||||
protected static final Integer GEMFIRE_CACHE_SERVER_PORT =
|
||||
Integer.getInteger("spring.session.data.gemfire.cache.server.port", CacheServer.DEFAULT_PORT);
|
||||
|
||||
public static void main(String[] args) {
|
||||
newGemFireServer(args).run();
|
||||
}
|
||||
|
||||
private final String[] args;
|
||||
|
||||
public static GemFireServer newGemFireServer(String[] args) {
|
||||
return new GemFireServer(args);
|
||||
}
|
||||
|
||||
protected GemFireServer(String[] args) {
|
||||
this.args = Optional.ofNullable(args)
|
||||
.orElseThrow(() -> new IllegalArgumentException("GemFireServer process arguments are required"));
|
||||
}
|
||||
|
||||
protected String[] getArguments() {
|
||||
return this.args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
run(getArguments());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected void run(String[] args) {
|
||||
createClusteredSpringSessionsRegion(addCacheServer(gemfireCache(gemfireProperties())));
|
||||
}
|
||||
|
||||
protected Properties gemfireProperties() {
|
||||
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", "o.s.s.d.g.server.GemFireServer");
|
||||
gemfireProperties.setProperty("jmx-manager", "true");
|
||||
//gemfireProperties.setProperty("log-file", "gemfire-server.log");
|
||||
gemfireProperties.setProperty("log-level", "error");
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
protected Cache gemfireCache(Properties gemfireProperties) {
|
||||
return new CacheFactory(gemfireProperties).create();
|
||||
}
|
||||
|
||||
protected Cache addCacheServer(Cache gemfireCache) {
|
||||
|
||||
try {
|
||||
CacheServer cacheServer = gemfireCache.addCacheServer();
|
||||
|
||||
cacheServer.setHostnameForClients("localhost");
|
||||
cacheServer.setPort(GEMFIRE_CACHE_SERVER_PORT);
|
||||
cacheServer.start();
|
||||
|
||||
return gemfireCache;
|
||||
}
|
||||
catch (IOException cause) {
|
||||
throw new RuntimeException("GemFire CacheServer failed to start", cause);
|
||||
}
|
||||
}
|
||||
|
||||
protected Cache createClusteredSpringSessionsRegion(Cache gemfireCache) {
|
||||
|
||||
RegionFactory<Object, Object> clusteredSpringSessionsRegion =
|
||||
gemfireCache.createRegionFactory(RegionShortcut.PARTITION);
|
||||
|
||||
clusteredSpringSessionsRegion.setEntryIdleTimeout(
|
||||
new ExpirationAttributes(Long.valueOf(TimeUnit.MINUTES.toSeconds(30)).intValue(),
|
||||
ExpirationAction.INVALIDATE));
|
||||
|
||||
clusteredSpringSessionsRegion.create("ClusteredSpringSessions");
|
||||
|
||||
return gemfireCache;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user