diff --git a/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepository.java b/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepository.java index 3103196..89a88da 100644 --- a/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepository.java +++ b/spring-session-data-geode/src/main/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepository.java @@ -849,14 +849,6 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi return this.id; } - public T getAttributes() { - return this.sessionAttributes; - } - - public Set getAttributeNames() { - return getAttributes().getAttributeNames(); - } - public void setAttribute(String attributeName, Object attributeValue) { getAttributes().setAttribute(attributeName, attributeValue); } @@ -869,6 +861,14 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi return getAttributes().getAttribute(attributeName); } + public Set getAttributeNames() { + return getAttributes().getAttributeNames(); + } + + public T getAttributes() { + return this.sessionAttributes; + } + public synchronized Instant getCreationTime() { return this.creationTime; } @@ -891,11 +891,18 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi return !isExpirationDisabled(duration); } + private boolean isLastAccessedTimeValid(Instant lastAccessedTime) { + return lastAccessedTime != null; + } + public synchronized void setLastAccessedTime(Instant lastAccessedTime) { - triggerDelta(!ObjectUtils.nullSafeEquals(this.lastAccessedTime, lastAccessedTime)); + if (isLastAccessedTimeValid(lastAccessedTime)) { - this.lastAccessedTime = lastAccessedTime; + triggerDelta(!ObjectUtils.nullSafeEquals(this.lastAccessedTime, lastAccessedTime)); + + this.lastAccessedTime = lastAccessedTime; + } } public synchronized Instant getLastAccessedTime() { diff --git a/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepositoryTests.java b/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepositoryTests.java index bb64e98..5c8c0de 100644 --- a/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepositoryTests.java +++ b/spring-session-data-geode/src/test/java/org/springframework/session/data/gemfire/AbstractGemFireOperationsSessionRepositoryTests.java @@ -1537,22 +1537,90 @@ public class AbstractGemFireOperationsSessionRepositoryTests { @Test public void isExpiredWhenSessionIsInactiveReturnsTrue() { - int expectedMaxInactiveIntervalInSeconds = 60; + Duration maxInactiveInterval = Duration.ofMillis(1); - GemFireSession session = GemFireSession.create(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds)); + GemFireSession session = GemFireSession.create(maxInactiveInterval); assertThat(session).isNotNull(); - assertThat(session.getMaxInactiveInterval()) - .isEqualTo(Duration.ofSeconds(expectedMaxInactiveIntervalInSeconds)); + assertThat(session.getMaxInactiveInterval()).isEqualTo(maxInactiveInterval); - Instant twoHoursAgo = Instant.ofEpochMilli(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2)); + long diff; - session.setLastAccessedTime(twoHoursAgo); + do { + diff = System.currentTimeMillis() - session.getLastAccessedTime().toEpochMilli(); + } + while (diff < maxInactiveInterval.toMillis() + 1); - assertThat(session.getLastAccessedTime()).isEqualTo(twoHoursAgo); assertThat(session.isExpired()).isTrue(); } + @Test + public void setAndGetLastAccessedTime() { + + Instant inTheBeginning = Instant.now(); + + GemFireSession session = GemFireSession.create(); + + assertThat(session).isNotNull(); + assertThat(session.getLastAccessedTime()).isAfterOrEqualTo(inTheBeginning); + assertThat(session.getLastAccessedTime()).isBeforeOrEqualTo(Instant.now()); + + Instant lastAccessedTime = session.getLastAccessedTime(); + + session.setLastAccessedTime(Instant.now()); + + assertThat(session.getLastAccessedTime()).isAfterOrEqualTo(lastAccessedTime); + assertThat(session.getLastAccessedTime()).isBeforeOrEqualTo(Instant.now()); + + lastAccessedTime = session.getLastAccessedTime(); + + session.setLastAccessedTime(lastAccessedTime.plusSeconds(5)); + + assertThat(session.getLastAccessedTime()).isAfter(lastAccessedTime); + assertThat(session.getLastAccessedTime()).isEqualTo(lastAccessedTime.plusSeconds(5)); + } + + @Test + public void setLastAccessedTimeInThePast() { + + GemFireSession session = GemFireSession.create(); + + assertThat(session).isNotNull(); + + Instant lastAccessedTime = session.getLastAccessedTime(); + + assertThat(lastAccessedTime).isNotNull(); + assertThat(lastAccessedTime).isBeforeOrEqualTo(Instant.now()); + + session.setLastAccessedTime(lastAccessedTime.minusMillis(1)); + + assertThat(session.getLastAccessedTime()).isEqualTo(lastAccessedTime.minusMillis(1)); + assertThat(session.getLastAccessedTime()).isBefore(Instant.now()); + + session.setLastAccessedTime(lastAccessedTime.minusSeconds(300)); + + assertThat(session.getLastAccessedTime()).isEqualTo(lastAccessedTime.minusSeconds(300)); + assertThat(session.getLastAccessedTime()).isBefore(Instant.now()); + } + + @Test + public void setLastAccessedTimeCannotBeSetToNull() { + + GemFireSession session = GemFireSession.create(); + + assertThat(session).isNotNull(); + + Instant lastAccessedTime = session.getLastAccessedTime(); + + assertThat(lastAccessedTime).isNotNull(); + assertThat(lastAccessedTime).isBeforeOrEqualTo(Instant.now()); + + session.setLastAccessedTime(null); + + assertThat(session.getLastAccessedTime()).isEqualTo(lastAccessedTime); + assertThat(lastAccessedTime).isBeforeOrEqualTo(Instant.now()); + } + @Test public void setAndGetPrincipalName() { @@ -1586,7 +1654,9 @@ public class AbstractGemFireOperationsSessionRepositoryTests { @SuppressWarnings("serial") DeltaCapableGemFireSession session = new DeltaCapableGemFireSession(); - session.setLastAccessedTime(Instant.ofEpochMilli(1L)); + Instant lastAccessedTime = session.getLastAccessedTime().plusSeconds(1); + + session.setLastAccessedTime(lastAccessedTime); session.setMaxInactiveInterval(Duration.ofSeconds(300L)); session.setAttribute("attributeOne", "test"); @@ -1596,7 +1666,8 @@ public class AbstractGemFireOperationsSessionRepositoryTests { assertThat(session.hasDelta()).isTrue(); - verify(mockDataOutput, times(1)).writeLong(eq(1L)); + verify(mockDataOutput, times(1)).writeUTF(eq(session.getId())); + verify(mockDataOutput, times(1)).writeLong(eq(lastAccessedTime.toEpochMilli())); verify(mockDataOutput, times(1)).writeLong(eq(300L)); verify(mockDataOutput, times(1)).writeInt(eq(1)); verify(mockDataOutput, times(1)).writeUTF(eq("attributeOne")); @@ -1607,8 +1678,10 @@ public class AbstractGemFireOperationsSessionRepositoryTests { DataInput mockDataInput = mock(DataInput.class); + Instant lastAccessedTime = Instant.now().plusSeconds(5); + when(mockDataInput.readUTF()).thenReturn("1"); - when(mockDataInput.readLong()).thenReturn(1L).thenReturn(600L); + when(mockDataInput.readLong()).thenReturn(lastAccessedTime.toEpochMilli()).thenReturn(300L); when(mockDataInput.readInt()).thenReturn(0); DeltaCapableGemFireSession session = new DeltaCapableGemFireSession(); @@ -1619,9 +1692,9 @@ public class AbstractGemFireOperationsSessionRepositoryTests { assertThat(session.getId()).isEqualTo("1"); assertThat(session.getCreationTime()).isEqualTo(creationTime); - assertThat(session.getLastAccessedTime()).isEqualTo(Instant.ofEpochMilli(1L)); + assertThat(session.getLastAccessedTime()).isEqualTo(lastAccessedTime); assertThat(session.hasDelta()).isTrue(); - assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(600L)); + assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(300L)); assertThat(session.getAttributeNames().isEmpty()).isTrue(); verify(mockDataInput, times(1)).readUTF(); @@ -2393,7 +2466,8 @@ public class AbstractGemFireOperationsSessionRepositoryTests { assertThat(this.session).isNotNull(); assertThat(this.session.getId()).isEqualTo("1"); - assertThat(this.session.getCreationTime().compareTo(beforeOrAtCreationTime)).isGreaterThanOrEqualTo(0); + assertThat(this.session.getCreationTime()).isAfterOrEqualTo(this.beforeOrAtCreationTime); + assertThat(this.session.getCreationTime()).isBeforeOrEqualTo(Instant.now()); assertThat(this.session.getLastAccessedTime()).isEqualTo(this.session.getCreationTime()); assertThat(this.session.getMaxInactiveInterval()).isEqualTo(Duration.ZERO); assertThat(this.session.getPrincipalName()).isNull(); @@ -2401,7 +2475,7 @@ public class AbstractGemFireOperationsSessionRepositoryTests { this.expectedCreationTime = this.session.getCreationTime(); - this.session.setLastAccessedTime(Instant.MIN); + this.session.setLastAccessedTime(this.expectedCreationTime.plusSeconds(1)); this.session.setMaxInactiveInterval(Duration.ofSeconds(60L)); this.session.setPrincipalName("jxblum"); } @@ -2415,15 +2489,16 @@ public class AbstractGemFireOperationsSessionRepositoryTests { assertThat(this.session).isNotNull(); assertThat(this.session.getId()).isEqualTo("1"); assertThat(this.session.getCreationTime()).isEqualTo(this.expectedCreationTime); - assertThat(this.session.getLastAccessedTime()).isEqualTo(Instant.MIN); + assertThat(this.session.getLastAccessedTime()).isEqualTo(this.expectedCreationTime.plusSeconds(1)); assertThat(this.session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(60L)); assertThat(this.session.getPrincipalName()).isEqualTo("jxblum"); assertThat(this.session.getAttributeNames()).hasSize(1); - assertThat(this.session.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME)).isEqualTo("jxblum"); + assertThat(this.session.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME)) + .isEqualTo("jxblum"); - this.session.setAttribute("tennis", "ping"); this.session.setAttribute("junk", "test"); - this.session.setLastAccessedTime(Instant.ofEpochSecond(1L)); + this.session.setAttribute("tennis", "ping"); + this.session.setLastAccessedTime(this.expectedCreationTime.plusSeconds(2)); this.session.setMaxInactiveInterval(Duration.ofSeconds(120L)); this.session.setPrincipalName("rwinch"); @@ -2432,7 +2507,7 @@ public class AbstractGemFireOperationsSessionRepositoryTests { assertThat(this.session).isNotNull(); assertThat(this.session.getId()).isEqualTo("1"); assertThat(this.session.getCreationTime()).isEqualTo(this.expectedCreationTime); - assertThat(this.session.getLastAccessedTime()).isEqualTo(Instant.ofEpochSecond(2L)); + assertThat(this.session.getLastAccessedTime()).isEqualTo(this.expectedCreationTime.plusSeconds(3)); assertThat(this.session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(180L)); assertThat(this.session.getPrincipalName()).isEqualTo("rwinch"); assertThat(this.session.getAttributeNames()).hasSize(3); @@ -2455,18 +2530,18 @@ public class AbstractGemFireOperationsSessionRepositoryTests { assertThat(this.session).isNotNull(); assertThat(this.session.getId()).isEqualTo("1"); assertThat(this.session.getCreationTime()).isEqualTo(this.expectedCreationTime); - assertThat(this.session.getLastAccessedTime()).isEqualTo(Instant.ofEpochSecond(1L)); + assertThat(this.session.getLastAccessedTime()).isEqualTo(this.expectedCreationTime.plusSeconds(2)); assertThat(this.session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(120L)); assertThat(this.session.getPrincipalName()).isEqualTo("rwinch"); assertThat(this.session.getAttributeNames()).hasSize(3); - assertThat(this.session.getAttributeNames()).containsAll(asSet("tennis", "junk")); + assertThat(this.session.getAttributeNames()).containsAll(asSet("junk", "tennis")); assertThat(this.session.getAttribute("junk")).isEqualTo("test"); assertThat(this.session.getAttribute("tennis")).isEqualTo("ping"); this.session.setAttribute("tennis", "pong"); this.session.setAttribute("greeting", "hello"); this.session.removeAttribute("junk"); - this.session.setLastAccessedTime(Instant.ofEpochSecond(2L)); + this.session.setLastAccessedTime(this.expectedCreationTime.plusSeconds(3)); this.session.setMaxInactiveInterval(Duration.ofSeconds(180L)); this.session.setPrincipalName("rwinch"); }