From 58689388c23f918178fcf0ecdbf0dbc33e4db488 Mon Sep 17 00:00:00 2001 From: John Blum Date: Wed, 20 Nov 2019 18:45:54 -0800 Subject: [PATCH] Add integration test for IndexMaintenanceException caused by IMQException caused by PdxSerializationException ultimately caused by ClassNotFoundException on Session object updates. Adds additional integration test covering the situation where users add application domain objects to the Session as Session Attribute values and a ClassNotFoundExcepiton occurs on the server during an Index Maintenance Operation when the Session is updated and the /ClusteredSpringSessions Region contains an OQL RANGE/FUNCTIONAL Index for 'principalName'. Resolves gh-45. Resolves gh-47. --- ...NoServerConfigurationIntegrationTests.java | 58 +++++++++++++++++-- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/serialization/pdx/SessionSerializationWithPdxRequiresNoServerConfigurationIntegrationTests.java b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/serialization/pdx/SessionSerializationWithPdxRequiresNoServerConfigurationIntegrationTests.java index d6f7dc4..59105ba 100644 --- a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/serialization/pdx/SessionSerializationWithPdxRequiresNoServerConfigurationIntegrationTests.java +++ b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/serialization/pdx/SessionSerializationWithPdxRequiresNoServerConfigurationIntegrationTests.java @@ -13,7 +13,6 @@ * 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; @@ -42,6 +41,7 @@ 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.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.session.Session; import org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests; import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository.GemFireSession; @@ -125,8 +125,8 @@ public class SessionSerializationWithPdxRequiresNoServerConfigurationIntegration System.setProperty("spring.session.data.gemfire.cache.server.port", String.valueOf(port)); String classpath = buildClassPathContainingJarFiles("javax.transaction-api", "antlr", - "commons-lang", "commons-io", "fastutil", "log4j-api", "log4j-core", "geode-common", "geode-core", - "geode-management", "jgroups", "micrometer-core", "shiro-core", "slf4j-api"); + "commons-lang", "commons-io", "fastutil", "log4j-api", "log4j-to-slf4j", "logback-classic", "logback-core", + "geode-common", "geode-core", "geode-management", "jgroups", "micrometer-core", "shiro-core", "slf4j-api"); String processWorkingDirectoryPathname = String.format("gemfire-server-pdx-serialization-tests-%1$s", TIMESTAMP.format(new Date())); @@ -153,7 +153,10 @@ public class SessionSerializationWithPdxRequiresNoServerConfigurationIntegration waitForProcessToStop(server, processWorkingDirectory)); }); - if (Boolean.valueOf(System.getProperty("spring.session.data.gemfire.fork.clean", Boolean.TRUE.toString()))) { + boolean forkClean = !System.getProperties().containsKey("spring.session.data.gemfire.fork.clean") + || Boolean.getBoolean("spring.session.data.gemfire.fork.clean"); + + if (forkClean) { FileSystemUtils.deleteRecursively(processWorkingDirectory); } } @@ -172,10 +175,10 @@ public class SessionSerializationWithPdxRequiresNoServerConfigurationIntegration Session sessionById = get(session.getId()); assertThat(sessionById).isEqualTo(session); + assertThat(sessionById).isNotSameAs(session); assertThat(sessionById.isExpired()).isFalse(); - Map sessionsByPrincipalName = this.sessionRepository.findByIndexNameAndIndexValue( - GemFireOperationsSessionRepository.PRINCIPAL_NAME_INDEX_NAME, "jonDoe"); + Map sessionsByPrincipalName = this.sessionRepository.findByPrincipalName("jonDoe"); assertThat(sessionsByPrincipalName).hasSize(1); @@ -183,10 +186,53 @@ public class SessionSerializationWithPdxRequiresNoServerConfigurationIntegration assertThat(sessionByPrincipalName).isInstanceOf(GemFireSession.class); assertThat(sessionByPrincipalName).isEqualTo(session); + assertThat(sessionByPrincipalName).isNotSameAs(session); assertThat(sessionByPrincipalName.isExpired()).isFalse(); assertThat(((GemFireSession) sessionByPrincipalName).getPrincipalName()).isEqualTo("jonDoe"); } + @Test + public void operationsOnSessionContainingApplicationDomainModelObjectIsSuccessful() { + + UsernamePasswordAuthenticationToken jxblumToken = + new UsernamePasswordAuthenticationToken("jxblum", "p@55w0rd"); + + Session session = createSession("janeDoe"); + + assertThat(session).isInstanceOf(GemFireSession.class); + + session.setAttribute("userToken", jxblumToken); + + assertThat(session.getId()).isNotNull(); + assertThat(session.getCreationTime()).isBeforeOrEqualTo(Instant.now()); + assertThat(session.isExpired()).isFalse(); + assertThat(session.getAttribute("userToken")) + .isEqualTo(jxblumToken); + + Session savedSession = save(session); + + assertThat(savedSession).isEqualTo(session); + assertThat(savedSession).isInstanceOf(GemFireSession.class); + + // NOTE: You must update and save the Session again, after it has already been saved to cause Apache Geode to + // update the 'principalNameIndex' OQL Index on an Index Maintenance Operation!!! + ((GemFireSession) savedSession).setPrincipalName("pieDoe"); + + savedSession = save(touch(savedSession)); + + assertThat(savedSession).isEqualTo(session); + + Session loadedSession = get(savedSession.getId()); + + assertThat(loadedSession).isEqualTo(savedSession); + assertThat(loadedSession).isNotSameAs(savedSession); + assertThat(loadedSession.getCreationTime()).isEqualTo(savedSession.getCreationTime()); + assertThat(loadedSession.getLastAccessedTime()).isAfterOrEqualTo(savedSession.getLastAccessedTime()); + assertThat(loadedSession.isExpired()).isFalse(); + assertThat(session.getAttribute("userToken")) + .isEqualTo(jxblumToken); + } + @ClientCacheApplication(logLevel = GEMFIRE_LOG_LEVEL, subscriptionEnabled = true) @EnableGemFireHttpSession(poolName = "DEFAULT") static class GemFireClientConfiguration {