Ignore cache Session Region LOCAL_LOAD_CREATE EntryEvents on SessionEventHandlerCacheListenerAdapter.afterCreate(:EntryEvent) invocations.
This commit is contained in:
@@ -42,6 +42,7 @@ import org.apache.geode.Delta;
|
||||
import org.apache.geode.InvalidDeltaException;
|
||||
import org.apache.geode.cache.EntryEvent;
|
||||
import org.apache.geode.cache.InterestResultPolicy;
|
||||
import org.apache.geode.cache.Operation;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
@@ -748,12 +749,12 @@ public abstract class AbstractGemFireOperationsSessionRepository
|
||||
* @return a new {@link GemFireSession}.
|
||||
* @see #isUsingDataSerialization()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings("unchecked" )
|
||||
public static <T extends GemFireSessionAttributes> GemFireSession<T> create() {
|
||||
|
||||
return isUsingDataSerialization()
|
||||
? (GemFireSession<T>) new DeltaCapableGemFireSession()
|
||||
: new GemFireSession();
|
||||
: new GemFireSession<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,6 +765,7 @@ public abstract class AbstractGemFireOperationsSessionRepository
|
||||
* @see org.springframework.session.Session
|
||||
* @see #isUsingDataSerialization()
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static GemFireSession copy(@NonNull Session session) {
|
||||
|
||||
return isUsingDataSerialization()
|
||||
@@ -780,6 +782,7 @@ public abstract class AbstractGemFireOperationsSessionRepository
|
||||
* or return a copy of the given {@link Session} as a {@link GemFireSession}.
|
||||
* @see #copy(Session)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static GemFireSession from(@NonNull Session session) {
|
||||
return session instanceof GemFireSession ? (GemFireSession) session : copy(session);
|
||||
}
|
||||
@@ -1475,6 +1478,7 @@ public abstract class AbstractGemFireOperationsSessionRepository
|
||||
public void afterCreate(EntryEvent<Object, Session> event) {
|
||||
|
||||
Optional.ofNullable(event)
|
||||
.filter(this::isNotLocalLoadEvent)
|
||||
.filter(this::remember)
|
||||
.ifPresent(it -> getSessionRepository()
|
||||
.publishEvent(newSessionCreatedEvent(toSession(it.getNewValue(), it.getKey()))));
|
||||
@@ -1633,6 +1637,32 @@ public abstract class AbstractGemFireOperationsSessionRepository
|
||||
return this.cachedSessionIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to determine whether the {@link Region} {@link EntryEvent} is
|
||||
* a {@link Operation#LOCAL_LOAD_CREATE} or a {@link Operation#LOCAL_LOAD_UPDATE}.
|
||||
*
|
||||
* @param event {@link Region} {@link EntryEvent} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link Region} {@link EntryEvent} is a local load based event.
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see #isNotLocalLoadEvent(EntryEvent)
|
||||
*/
|
||||
protected boolean isLocalLoadEvent(@Nullable EntryEvent<?, ?> event) {
|
||||
return event != null && event.getOperation() != null && event.getOperation().isLocalLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to determine whether the {@link Region} {@link EntryEvent} is
|
||||
* a {@link Operation#LOCAL_LOAD_CREATE} or a {@link Operation#LOCAL_LOAD_UPDATE}.
|
||||
*
|
||||
* @param event {@link Region} {@link EntryEvent} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link Region} {@link EntryEvent} is a local load based event.
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see #isLocalLoadEvent(EntryEvent)
|
||||
*/
|
||||
protected boolean isNotLocalLoadEvent(@Nullable EntryEvent<?, ?> event) {
|
||||
return !isLocalLoadEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link Session#getId() Session ID} has been remembered.
|
||||
*
|
||||
@@ -1760,13 +1790,14 @@ public abstract class AbstractGemFireOperationsSessionRepository
|
||||
*/
|
||||
protected Session toSession(@Nullable Object target, Object sessionId) {
|
||||
|
||||
return isSession(target) ? (Session) target
|
||||
return isSession(target)
|
||||
? (Session) target
|
||||
: Optional.ofNullable(sessionId)
|
||||
.filter(SessionUtils::isValidSessionId)
|
||||
.map(Object::toString)
|
||||
.map(SessionIdHolder::create)
|
||||
.orElseThrow(() -> newIllegalStateException(
|
||||
"Session or the Session ID [%s] must be known to trigger a Session event", sessionId));
|
||||
"The Session or the Session ID [%s] must be known to trigger a Session event", sessionId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
@@ -79,8 +80,6 @@ import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.gemfire.GemfireOperations;
|
||||
@@ -104,8 +103,10 @@ import org.springframework.session.events.SessionDestroyedEvent;
|
||||
import org.springframework.session.events.SessionExpiredEvent;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractGemFireOperationsSessionRepository}.
|
||||
* Unit Tests for {@link AbstractGemFireOperationsSessionRepository}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.time.Duration
|
||||
@@ -120,11 +121,13 @@ import org.springframework.util.ObjectUtils;
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.mockito.Spy
|
||||
* @see org.apache.geode.Delta
|
||||
* @see org.apache.geode.cache.AttributesMutator
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see org.apache.geode.cache.Operation
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.RegionAttributes
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
* @see org.springframework.data.gemfire.GemfireTemplate
|
||||
* @see org.springframework.session.FindByIndexNameSessionRepository
|
||||
* @see org.springframework.session.Session
|
||||
@@ -136,6 +139,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
|
||||
protected static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 300;
|
||||
@@ -156,7 +160,6 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
private Session mockSession;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("all")
|
||||
public void setup() {
|
||||
|
||||
this.sessionRepository = new TestGemFireOperationsSessionRepository(new GemfireTemplate(this.mockRegion));
|
||||
@@ -1040,6 +1043,23 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
verify(this.sessionRepository, never()).publishEvent(any(ApplicationEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void afterCreateHandlesLocalLoadCreateDoesNotPublishSessionCreatedEvent() {
|
||||
|
||||
SessionEventHandlerCacheListenerAdapter sessionEventHandler =
|
||||
spy(this.sessionRepository.newSessionEventHandler());
|
||||
|
||||
EntryEvent mockEntryEvent = mock(EntryEvent.class);
|
||||
|
||||
when(mockEntryEvent.getOperation()).thenReturn(Operation.LOCAL_LOAD_CREATE);
|
||||
|
||||
sessionEventHandler.afterCreate(mockEntryEvent);
|
||||
|
||||
verify(mockEntryEvent, atLeastOnce()).getOperation();
|
||||
verify(this.sessionRepository, never()).publishEvent(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void afterCreateHandlesNullSessionWillNotPublishSessionCreatedEvent() {
|
||||
@@ -1137,7 +1157,9 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Session or the Session ID [null] must be known to trigger a Session event");
|
||||
assertThat(expected)
|
||||
.hasMessage("The Session or the Session ID [null] must be known to trigger a Session event");
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
@@ -1561,6 +1583,80 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
verify(sessionEventHandler, times(1)).getSessionRepository();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLocalLoadEventWithNullEvent() {
|
||||
|
||||
SessionEventHandlerCacheListenerAdapter sessionEventHandler = this.sessionRepository.newSessionEventHandler();
|
||||
|
||||
assertThat(sessionEventHandler).isNotNull();
|
||||
assertThat(sessionEventHandler.isLocalLoadEvent(null)).isFalse();
|
||||
assertThat(sessionEventHandler.isNotLocalLoadEvent(null)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLocalLoadEventWithNullOperation() {
|
||||
|
||||
SessionEventHandlerCacheListenerAdapter sessionEventHandler = this.sessionRepository.newSessionEventHandler();
|
||||
|
||||
EntryEvent mockEntryEvent = mock(EntryEvent.class);
|
||||
|
||||
when(mockEntryEvent.getOperation()).thenReturn(null);
|
||||
|
||||
assertThat(sessionEventHandler).isNotNull();
|
||||
assertThat(sessionEventHandler.isLocalLoadEvent(mockEntryEvent)).isFalse();
|
||||
assertThat(sessionEventHandler.isNotLocalLoadEvent(mockEntryEvent)).isTrue();
|
||||
|
||||
verify(mockEntryEvent, times(2)).getOperation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLocalLoadEventWithFunctionExecutionOperation() {
|
||||
|
||||
SessionEventHandlerCacheListenerAdapter sessionEventHandler = this.sessionRepository.newSessionEventHandler();
|
||||
|
||||
EntryEvent mockEntryEvent = mock(EntryEvent.class);
|
||||
|
||||
when(mockEntryEvent.getOperation()).thenReturn(Operation.FUNCTION_EXECUTION);
|
||||
|
||||
assertThat(sessionEventHandler).isNotNull();
|
||||
assertThat(sessionEventHandler.isLocalLoadEvent(mockEntryEvent)).isFalse();
|
||||
assertThat(sessionEventHandler.isNotLocalLoadEvent(mockEntryEvent)).isTrue();
|
||||
|
||||
verify(mockEntryEvent, times(4)).getOperation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLocalLoadEventWithLocalLoadCreateOperation() {
|
||||
|
||||
SessionEventHandlerCacheListenerAdapter sessionEventHandler = this.sessionRepository.newSessionEventHandler();
|
||||
|
||||
EntryEvent mockEntryEvent = mock(EntryEvent.class);
|
||||
|
||||
when(mockEntryEvent.getOperation()).thenReturn(Operation.LOCAL_LOAD_CREATE);
|
||||
|
||||
assertThat(sessionEventHandler).isNotNull();
|
||||
assertThat(sessionEventHandler.isLocalLoadEvent(mockEntryEvent)).isTrue();
|
||||
assertThat(sessionEventHandler.isNotLocalLoadEvent(mockEntryEvent)).isFalse();
|
||||
|
||||
verify(mockEntryEvent, times(4)).getOperation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLocalLoadEventWithLocalLoadUpdateOperation() {
|
||||
|
||||
SessionEventHandlerCacheListenerAdapter sessionEventHandler = this.sessionRepository.newSessionEventHandler();
|
||||
|
||||
EntryEvent mockEntryEvent = mock(EntryEvent.class);
|
||||
|
||||
when(mockEntryEvent.getOperation()).thenReturn(Operation.LOCAL_LOAD_UPDATE);
|
||||
|
||||
assertThat(sessionEventHandler).isNotNull();
|
||||
assertThat(sessionEventHandler.isLocalLoadEvent(mockEntryEvent)).isTrue();
|
||||
assertThat(sessionEventHandler.isNotLocalLoadEvent(mockEntryEvent)).isFalse();
|
||||
|
||||
verify(mockEntryEvent, times(4)).getOperation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRememberedWithKnownSessionId() {
|
||||
|
||||
@@ -1621,7 +1717,6 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void forgetNullEntryEvent() {
|
||||
|
||||
SessionEventHandlerCacheListenerAdapter sessionEventHandler = this.sessionRepository.newSessionEventHandler();
|
||||
@@ -1887,7 +1982,7 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage("Session or the Session ID [%s] must be known to trigger a Session event",
|
||||
.hasMessage("The Session or the Session ID [%s] must be known to trigger a Session event",
|
||||
sessionId);
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
@@ -2157,6 +2252,7 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
assertThat(session.getAttributes()).isEmpty();
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void copyNullThrowsIllegalArgumentException() {
|
||||
|
||||
@@ -2275,6 +2371,7 @@ public class AbstractGemFireOperationsSessionRepositoryTests {
|
||||
verify(mockSession, never()).getAttribute(anyString());
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromNullSessionThrowsIllegalArgumentException() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user