diff --git a/spring-session-hazelcast/src/integration-test/java/org/springframework/session/hazelcast/config/annotation/web/http/EnableHazelcastHttpSessionEventsTests.java b/spring-session-hazelcast/src/integration-test/java/org/springframework/session/hazelcast/config/annotation/web/http/EnableHazelcastHttpSessionEventsTests.java index b88405cf..66cacdcf 100644 --- a/spring-session-hazelcast/src/integration-test/java/org/springframework/session/hazelcast/config/annotation/web/http/EnableHazelcastHttpSessionEventsTests.java +++ b/spring-session-hazelcast/src/integration-test/java/org/springframework/session/hazelcast/config/annotation/web/http/EnableHazelcastHttpSessionEventsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2018 the original author or authors. + * Copyright 2014-2019 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. @@ -181,6 +181,28 @@ public class EnableHazelcastHttpSessionEventsTests { assertThat(this.registry.receivedEvent(sessionToSave.getId())).isFalse(); } + @Test // gh-1300 + public void updateMaxInactiveIntervalTest() throws InterruptedException { + S sessionToSave = this.repository.createSession(); + sessionToSave.setMaxInactiveInterval(Duration.ofMinutes(30)); + this.repository.save(sessionToSave); + + assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue(); + assertThat(this.registry.getEvent(sessionToSave.getId())) + .isInstanceOf(SessionCreatedEvent.class); + this.registry.clear(); + + S sessionToUpdate = this.repository.findById(sessionToSave.getId()); + sessionToUpdate.setLastAccessedTime(Instant.now()); + sessionToUpdate.setMaxInactiveInterval(Duration.ofSeconds(1)); + this.repository.save(sessionToUpdate); + + assertThat(this.registry.receivedEvent(sessionToUpdate.getId())).isTrue(); + assertThat(this.registry.getEvent(sessionToUpdate.getId())) + .isInstanceOf(SessionExpiredEvent.class); + assertThat(this.repository.findById(sessionToUpdate.getId())).isNull(); + } + @Configuration @EnableHazelcastHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS) static class HazelcastSessionConfig { diff --git a/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/HazelcastSessionRepository.java b/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/HazelcastSessionRepository.java index 1c54c0a2..401249c4 100644 --- a/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/HazelcastSessionRepository.java +++ b/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/HazelcastSessionRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2018 the original author or authors. + * Copyright 2014-2019 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. @@ -48,6 +48,7 @@ import org.springframework.session.events.SessionCreatedEvent; import org.springframework.session.events.SessionDeletedEvent; import org.springframework.session.events.SessionExpiredEvent; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * A {@link org.springframework.session.SessionRepository} implementation that stores @@ -120,6 +121,9 @@ public class HazelcastSessionRepository implements */ public static final String PRINCIPAL_NAME_ATTRIBUTE = "principalName"; + private static final boolean SUPPORTS_SET_TTL = ClassUtils + .hasAtLeastOneMethodWithName(IMap.class, "setTtl"); + private static final Log logger = LogFactory.getLog(HazelcastSessionRepository.class); private final HazelcastInstance hazelcastInstance; @@ -238,6 +242,9 @@ public class HazelcastSessionRepository implements entryProcessor.setLastAccessedTime(session.getLastAccessedTime()); } if (session.maxInactiveIntervalChanged) { + if (SUPPORTS_SET_TTL) { + updateTtl(session); + } entryProcessor.setMaxInactiveInterval(session.getMaxInactiveInterval()); } if (!session.delta.isEmpty()) { @@ -248,6 +255,11 @@ public class HazelcastSessionRepository implements session.clearChangeFlags(); } + private void updateTtl(HazelcastSession session) { + this.sessions.setTtl(session.getId(), + session.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS); + } + @Override public HazelcastSession findById(String id) { MapSession saved = this.sessions.get(id); diff --git a/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java b/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java index 4ac713f2..fd274996 100644 --- a/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java +++ b/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2018 the original author or authors. + * Copyright 2014-2019 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. @@ -42,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; @@ -259,10 +260,12 @@ public class HazelcastSessionRepositoryTests { this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE); HazelcastSession session = this.repository.createSession(); + String sessionId = session.getId(); session.setMaxInactiveInterval(Duration.ofSeconds(1)); - verify(this.sessions, times(1)).set(eq(session.getId()), + verify(this.sessions, times(1)).set(eq(sessionId), eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS)); - verify(this.sessions, times(1)).executeOnKey(eq(session.getId()), + verify(this.sessions).setTtl(eq(sessionId), anyLong(), any()); + verify(this.sessions, times(1)).executeOnKey(eq(sessionId), any(EntryProcessor.class)); this.repository.save(session);