From a1ffa1c56a408c1ca558aa41f13a70f5d8067263 Mon Sep 17 00:00:00 2001 From: John Blum Date: Fri, 16 Sep 2022 13:29:24 -0700 Subject: [PATCH] Replace the SSDG project build.GemFireServer Gradle Plugin with STDG means of launching and managing Apache Geode servers for client/server integration tests. --- .../convention/SpringSampleWarPlugin.groovy | 6 ++ .../spring-session-sample-boot-gemfire.gradle | 2 +- .../java/sample/AttributeTests.java | 12 ++- .../java/sample/server/GemFireServer.java | 2 +- ...ple-javaconfig-gemfire-clientserver.gradle | 3 +- .../java/sample/AttributeTests.java | 1 - .../main/java/sample/client/ClientConfig.java | 2 +- .../main/java/sample/client/Initializer.java | 94 ++++++++++++++++++- .../java/sample/server/GemFireServer.java | 3 +- ...ion-sample-xml-gemfire-clientserver.gradle | 2 +- .../java/sample/AttributeTests.java | 1 - ...eGeodeServerWebApplicationInitializer.java | 87 +++++++++++++++++ .../ClientServerReadyBeanPostProcessor.java | 1 - .../java/sample/server/GemFireServer.java | 1 - .../webapp/WEB-INF/spring/session-client.xml | 1 + 15 files changed, 203 insertions(+), 15 deletions(-) create mode 100644 samples/xml/gemfire-clientserver/src/main/java/sample/client/ApacheGeodeServerWebApplicationInitializer.java diff --git a/buildSrc/src/main/groovy/io/spring/gradle/convention/SpringSampleWarPlugin.groovy b/buildSrc/src/main/groovy/io/spring/gradle/convention/SpringSampleWarPlugin.groovy index 829f4b4..6528fe4 100644 --- a/buildSrc/src/main/groovy/io/spring/gradle/convention/SpringSampleWarPlugin.groovy +++ b/buildSrc/src/main/groovy/io/spring/gradle/convention/SpringSampleWarPlugin.groovy @@ -64,9 +64,15 @@ class SpringSampleWarPlugin extends SpringSamplePlugin { group = 'Verification' description = 'Prepares the Web application server for Integration Testing' doFirst { + int cacheServerPort = getRandomPort(); project.gretty { + // classPath = project.sourceSets.integrationTest.runtimeClasspath.toSet() httpPort = getRandomPort() httpsPort = getRandomPort() + jvmArgs = [ + "-Dspring.data.gemfire.cache.server.port=$cacheServerPort", + "-Dspring.data.gemfire.pool.servers=localhost[$cacheServerPort]" + ] } } } diff --git a/samples/boot/gemfire/spring-session-sample-boot-gemfire.gradle b/samples/boot/gemfire/spring-session-sample-boot-gemfire.gradle index 197fc43..2a2a876 100644 --- a/samples/boot/gemfire/spring-session-sample-boot-gemfire.gradle +++ b/samples/boot/gemfire/spring-session-sample-boot-gemfire.gradle @@ -1,5 +1,5 @@ apply plugin: 'io.spring.convention.spring-sample-boot' -apply plugin: "gemfire-server" +// apply plugin: "gemfire-server" apply plugin: "application" dependencies { diff --git a/samples/boot/gemfire/src/integration-test/java/sample/AttributeTests.java b/samples/boot/gemfire/src/integration-test/java/sample/AttributeTests.java index 8c6ed84..26347b6 100644 --- a/samples/boot/gemfire/src/integration-test/java/sample/AttributeTests.java +++ b/samples/boot/gemfire/src/integration-test/java/sample/AttributeTests.java @@ -17,8 +17,11 @@ package sample; import static org.assertj.core.api.Assertions.assertThat; +import java.io.IOException; + import org.junit.After; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder; @@ -34,6 +38,7 @@ import org.openqa.selenium.WebDriver; import sample.client.Application; import sample.pages.HomePage; +import sample.server.GemFireServer; /** * @author EddĂș MelĂ©ndez @@ -41,13 +46,18 @@ import sample.pages.HomePage; @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.MOCK) @AutoConfigureMockMvc -public class AttributeTests { +public class AttributeTests extends ForkingClientServerIntegrationTestsSupport { @Autowired private MockMvc mockMvc; private WebDriver driver; + @BeforeClass + public static void startGeodeServer() throws IOException { + startGeodeServer(GemFireServer.class); + } + @Before public void setup() { this.driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc).build(); diff --git a/samples/boot/gemfire/src/main/java/sample/server/GemFireServer.java b/samples/boot/gemfire/src/main/java/sample/server/GemFireServer.java index f379a19..f758f36 100644 --- a/samples/boot/gemfire/src/main/java/sample/server/GemFireServer.java +++ b/samples/boot/gemfire/src/main/java/sample/server/GemFireServer.java @@ -35,7 +35,7 @@ import org.springframework.session.data.gemfire.config.annotation.web.http.Enabl */ // tag::class[] @SpringBootApplication // <1> -@CacheServerApplication(name = "SpringSessionDataGeodeBootSampleServer", logLevel = "error") // <2> +@CacheServerApplication(name = "SpringSessionDataGeodeBootSampleServer") // <2> @EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 20) // <3> public class GemFireServer { diff --git a/samples/javaconfig/gemfire-clientserver/spring-session-sample-javaconfig-gemfire-clientserver.gradle b/samples/javaconfig/gemfire-clientserver/spring-session-sample-javaconfig-gemfire-clientserver.gradle index 2230869..ba46d58 100644 --- a/samples/javaconfig/gemfire-clientserver/spring-session-sample-javaconfig-gemfire-clientserver.gradle +++ b/samples/javaconfig/gemfire-clientserver/spring-session-sample-javaconfig-gemfire-clientserver.gradle @@ -3,12 +3,13 @@ plugins { id "io.spring.convention.spring-sample-war" } -apply plugin: "gemfire-server" +// apply plugin: "gemfire-server" apply plugin: "application" dependencies { implementation project(':spring-session-data-geode') + implementation "io.github.classgraph:classgraph:4.8.149" implementation "org.springframework:spring-web" implementation "org.springframework.data:spring-data-geode-test" implementation jstlDependencies diff --git a/samples/javaconfig/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java b/samples/javaconfig/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java index 9e10998..5297512 100644 --- a/samples/javaconfig/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java +++ b/samples/javaconfig/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package sample; import static org.assertj.core.api.Assertions.assertThat; diff --git a/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/ClientConfig.java b/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/ClientConfig.java index 534d085..62d4bf7 100644 --- a/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/ClientConfig.java +++ b/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/ClientConfig.java @@ -24,7 +24,7 @@ import org.springframework.data.gemfire.tests.integration.ClientServerIntegratio import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession; // tag::class[] -@ClientCacheApplication(name = "SpringSessionDataGeodeJavaConfigSampleClient", logLevel = "error", +@ClientCacheApplication(name = "SpringSessionDataGeodeJavaConfigSampleClient", readTimeout = 15000, retryAttempts = 1, subscriptionEnabled = true) // <1> @EnableGemFireHttpSession(poolName = "DEFAULT") // <2> public class ClientConfig extends ClientServerIntegrationTestsSupport { diff --git a/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/Initializer.java b/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/Initializer.java index 09a62a5..904887c 100644 --- a/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/Initializer.java +++ b/samples/javaconfig/gemfire-clientserver/src/main/java/sample/client/Initializer.java @@ -13,16 +13,104 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package sample.client; +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport; +import org.springframework.data.gemfire.tests.process.ProcessWrapper; +import org.springframework.data.gemfire.util.CollectionUtils; +import org.springframework.lang.NonNull; import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer; +import org.springframework.util.StringUtils; + +import io.github.classgraph.ClassGraph; +import sample.server.GemFireServer; // tag::class[] public class Initializer extends AbstractHttpSessionApplicationInitializer { // <1> public Initializer() { - super(ClientConfig.class); // <2> + super(ApacheGeodeServerRunner.onStartup(ClientConfig.class)); // <2> + } + + static class ApacheGeodeServerRunner extends ForkingClientServerIntegrationTestsSupport { + + static @NonNull Class onStartup(@NonNull Class clientConfigurationType) { + + try { + + //System.err.printf("JAVA CLASSPATH [%s]%n", javaSystemClasspath()); + //System.err.printf("THREAD CONTEXT CLASSLOADER CLASSPATH [%s]%n", contextClassLoaderClasspath()); + //System.err.printf("CLASS-GRAPH CLASSLOADER CLASSPATH [%s]%n", classGraphClassLoaderClasspath()); + + registerGeodeServerRuntimeShutdownHook( + startGeodeServer(classGraphClasspath(), GemFireServer.class)); + + return clientConfigurationType; + } + catch(IOException cause) { + throw newRuntimeException(cause, "Failed to start the Apache Geode Server"); + } + } + + static String classGraphClasspath() { + + List classpathElements = CollectionUtils.nullSafeList(new ClassGraph().getClasspathURLs()).stream() + .filter(Objects::nonNull) + .map(URL::getFile) + .filter(StringUtils::hasText) + .toList(); + + return StringUtils.collectionToDelimitedString(classpathElements, System.getProperty("path.separator")); + } + + static ProcessWrapper registerGeodeServerRuntimeShutdownHook(ProcessWrapper geodeServer) { + + if (geodeServer != null) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + ForkingClientServerIntegrationTestsSupport.stop(geodeServer); + }, "Apache Geode Server Runtime Shutdown Hook")); + } + + return geodeServer; + } +// end::class[] + + static String javaSystemClasspath() { + return System.getProperty("java.class.path"); + } + + @SuppressWarnings("all") + static String threadContextClassLoaderClasspath() { + + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + + System.err.printf("THREAD CONTEXT CLASSLOADER TYPE [%s]%n", contextClassLoader != null + ? contextClassLoader.getClass().getName() : null); + + List classpathElements = Optional.ofNullable(Thread.currentThread()) + .map(Thread::getContextClassLoader) + .filter(URLClassLoader.class::isInstance) + .map(URLClassLoader.class::cast) + .map(URLClassLoader::getURLs) + .map(Stream::of) + .orElseGet(Stream::empty) + .filter(Objects::nonNull) + .map(URL::getFile) + .filter(StringUtils::hasText) + .collect(Collectors.toList()); + + return StringUtils.collectionToDelimitedString(classpathElements, System.getProperty("path.separator")); + } } } -// end::class[] diff --git a/samples/javaconfig/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java b/samples/javaconfig/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java index 6c4c1ce..ca04698 100644 --- a/samples/javaconfig/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java +++ b/samples/javaconfig/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package sample.server; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -21,7 +20,7 @@ import org.springframework.data.gemfire.config.annotation.CacheServerApplication import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession; // tag::class[] -@CacheServerApplication(name = "SpringSessionDataGeodeJavaConfigSampleServer", logLevel = "error") // <1> +@CacheServerApplication(name = "SpringSessionDataGeodeJavaConfigSampleServer") // <1> @EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30) // <2> public class GemFireServer { diff --git a/samples/xml/gemfire-clientserver/spring-session-sample-xml-gemfire-clientserver.gradle b/samples/xml/gemfire-clientserver/spring-session-sample-xml-gemfire-clientserver.gradle index 2230869..771f991 100644 --- a/samples/xml/gemfire-clientserver/spring-session-sample-xml-gemfire-clientserver.gradle +++ b/samples/xml/gemfire-clientserver/spring-session-sample-xml-gemfire-clientserver.gradle @@ -3,7 +3,7 @@ plugins { id "io.spring.convention.spring-sample-war" } -apply plugin: "gemfire-server" +// apply plugin: "gemfire-server" apply plugin: "application" dependencies { diff --git a/samples/xml/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java b/samples/xml/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java index 9e10998..5297512 100644 --- a/samples/xml/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java +++ b/samples/xml/gemfire-clientserver/src/integration-test/java/sample/AttributeTests.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package sample; import static org.assertj.core.api.Assertions.assertThat; diff --git a/samples/xml/gemfire-clientserver/src/main/java/sample/client/ApacheGeodeServerWebApplicationInitializer.java b/samples/xml/gemfire-clientserver/src/main/java/sample/client/ApacheGeodeServerWebApplicationInitializer.java new file mode 100644 index 0000000..3aec8b9 --- /dev/null +++ b/samples/xml/gemfire-clientserver/src/main/java/sample/client/ApacheGeodeServerWebApplicationInitializer.java @@ -0,0 +1,87 @@ +/* + * Copyright 2015-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package sample.client; + +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException; + +import java.io.IOException; +import java.net.URL; +import java.util.List; +import java.util.Objects; + +import jakarta.servlet.ServletContext; + +import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport; +import org.springframework.data.gemfire.tests.process.ProcessWrapper; +import org.springframework.data.gemfire.util.CollectionUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.WebApplicationInitializer; + +import io.github.classgraph.ClassGraph; +import sample.server.GemFireServer; + +/** + * Spring {@link WebApplicationInitializer} used to bootstrap an Apache Geode server process. + * + * @author John Blum + * @see sample.server.GemFireServer + * @see org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport + * @see org.springframework.data.gemfire.tests.process.ProcessWrapper + * @see org.springframework.web.WebApplicationInitializer + * @since 3.0.0 + */ +public class ApacheGeodeServerWebApplicationInitializer extends ForkingClientServerIntegrationTestsSupport + implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext servletContext) { + + try { + + //System.err.printf("JAVA CLASSPATH [%s]%n", javaSystemClasspath()); + //System.err.printf("THREAD CONTEXT CLASSLOADER CLASSPATH [%s]%n", contextClassLoaderClasspath()); + //System.err.printf("CLASS-GRAPH CLASSLOADER CLASSPATH [%s]%n", classGraphClassLoaderClasspath()); + + registerGeodeServerRuntimeShutdownHook( + startGeodeServer(classGraphClasspath(), GemFireServer.class)); + } + catch(IOException cause) { + throw newRuntimeException(cause, "Failed to start the Apache Geode Server"); + } + } + + static String classGraphClasspath() { + + List classpathElements = CollectionUtils.nullSafeList(new ClassGraph().getClasspathURLs()).stream() + .filter(Objects::nonNull) + .map(URL::getFile) + .filter(StringUtils::hasText) + .toList(); + + return StringUtils.collectionToDelimitedString(classpathElements, System.getProperty("path.separator")); + } + + static ProcessWrapper registerGeodeServerRuntimeShutdownHook(ProcessWrapper geodeServer) { + + if (geodeServer != null) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + ForkingClientServerIntegrationTestsSupport.stop(geodeServer); + }, "Apache Geode Server Runtime Shutdown Hook")); + } + + return geodeServer; + } +} diff --git a/samples/xml/gemfire-clientserver/src/main/java/sample/client/ClientServerReadyBeanPostProcessor.java b/samples/xml/gemfire-clientserver/src/main/java/sample/client/ClientServerReadyBeanPostProcessor.java index 786406a..48b18cc 100644 --- a/samples/xml/gemfire-clientserver/src/main/java/sample/client/ClientServerReadyBeanPostProcessor.java +++ b/samples/xml/gemfire-clientserver/src/main/java/sample/client/ClientServerReadyBeanPostProcessor.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package sample.client; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/samples/xml/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java b/samples/xml/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java index 15b3236..fc7fa86 100644 --- a/samples/xml/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java +++ b/samples/xml/gemfire-clientserver/src/main/java/sample/server/GemFireServer.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package sample.server; import org.springframework.context.annotation.AnnotationConfigApplicationContext; diff --git a/samples/xml/gemfire-clientserver/src/main/webapp/WEB-INF/spring/session-client.xml b/samples/xml/gemfire-clientserver/src/main/webapp/WEB-INF/spring/session-client.xml index 01c5979..33bed7c 100644 --- a/samples/xml/gemfire-clientserver/src/main/webapp/WEB-INF/spring/session-client.xml +++ b/samples/xml/gemfire-clientserver/src/main/webapp/WEB-INF/spring/session-client.xml @@ -17,6 +17,7 @@ +