Adapt to API changes in Spring Session core 2.0.0.RC2.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.springframework.session.data.gemfire;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -59,6 +60,7 @@ import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
|
||||
import org.springframework.session.data.gemfire.support.GemFireUtils;
|
||||
import org.springframework.session.data.gemfire.support.SessionIdHolder;
|
||||
import org.springframework.session.events.SessionCreatedEvent;
|
||||
import org.springframework.session.events.SessionDeletedEvent;
|
||||
import org.springframework.session.events.SessionDestroyedEvent;
|
||||
@@ -79,9 +81,11 @@ import org.apache.commons.logging.LogFactory;
|
||||
* @see org.apache.geode.DataSerializer
|
||||
* @see org.apache.geode.Delta
|
||||
* @see org.apache.geode.Instantiator
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see org.apache.geode.cache.Operation
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.util.CacheListenerAdapter
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.context.ApplicationEvent
|
||||
* @see org.springframework.context.ApplicationEventPublisher
|
||||
* @see org.springframework.context.ApplicationEventPublisherAware
|
||||
* @see org.springframework.data.gemfire.GemfireOperations
|
||||
@@ -91,6 +95,10 @@ import org.apache.commons.logging.LogFactory;
|
||||
* @see org.springframework.session.SessionRepository
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
|
||||
* @see org.springframework.session.events.SessionCreatedEvent
|
||||
* @see org.springframework.session.events.SessionDeletedEvent
|
||||
* @see org.springframework.session.events.SessionDestroyedEvent
|
||||
* @see org.springframework.session.events.SessionExpiredEvent
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public abstract class AbstractGemFireOperationsSessionRepository extends CacheListenerAdapter<Object, Session>
|
||||
@@ -130,13 +138,11 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
/**
|
||||
* Constructs a new instance of {@link Log} using Apache Commons {@link LogFactory}.
|
||||
*
|
||||
* Used in testing to override the {@link Log} implementation with a mock.
|
||||
*
|
||||
* @return an instance of {@link Log} constructed from Apache commons-logging {@link LogFactory}.
|
||||
* @return a new instance of {@link Log} constructed from Apache commons-logging {@link LogFactory}.
|
||||
* @see org.apache.commons.logging.LogFactory#getLog(Class)
|
||||
* @see org.apache.commons.logging.Log
|
||||
*/
|
||||
Log newLogger() {
|
||||
private Log newLogger() {
|
||||
return LogFactory.getLog(getClass());
|
||||
}
|
||||
|
||||
@@ -232,8 +238,11 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @see #getMaxInactiveInterval()
|
||||
*/
|
||||
public int getMaxInactiveIntervalInSeconds() {
|
||||
return Optional.ofNullable(getMaxInactiveInterval()).map(Duration::getSeconds)
|
||||
.map(Long::intValue).orElse(0);
|
||||
|
||||
return Optional.ofNullable(getMaxInactiveInterval())
|
||||
.map(Duration::getSeconds)
|
||||
.map(Long::intValue)
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,17 +301,17 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
|
||||
/* (non-Javadoc) */
|
||||
boolean isCreate(EntryEvent<?, ?> event) {
|
||||
return (isCreate(event.getOperation()) && isNotUpdate(event) && isSessionOrNull(event.getNewValue()));
|
||||
return isCreate(event.getOperation()) && isNotUpdate(event) && isSession(event.getNewValue());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean isCreate(Operation operation) {
|
||||
return (operation.isCreate() && !Operation.LOCAL_LOAD_CREATE.equals(operation));
|
||||
return operation.isCreate() && !Operation.LOCAL_LOAD_CREATE.equals(operation);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean isNotUpdate(EntryEvent event) {
|
||||
return (isNotProxyRegion() || !this.cachedSessionIds.contains(ObjectUtils.nullSafeHashCode(event.getKey())));
|
||||
return isNotProxyRegion() || !this.cachedSessionIds.contains(ObjectUtils.nullSafeHashCode(event.getKey()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -316,70 +325,120 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine whether the developer is storing (HTTP) Sessions with other, arbitrary application
|
||||
* domain objects in the same GemFire cache {@link Region}; crazier things have happened!
|
||||
* Used to determine whether the application developer is storing (HTTP) Sessions with other, arbitrary
|
||||
* application domain objects in the same GemFire cache {@link Region}; crazier things have happened!
|
||||
*
|
||||
* @param obj {@link Object} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link Object} from the entry event is indeed
|
||||
* a {@link Session}.
|
||||
* @return a boolean value indicating whether the old/new {@link Object} from the {@link Region}
|
||||
* {@link EntryEvent} is indeed a {@link Session}.
|
||||
* @see org.springframework.session.Session
|
||||
*/
|
||||
private boolean isSessionOrNull(Object obj) {
|
||||
return (obj instanceof Session || obj == null);
|
||||
private boolean isSession(Object obj) {
|
||||
return obj instanceof Session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgets the given {@link Object session ID}.
|
||||
*
|
||||
* @param sessionId {@link Object} containing the session ID to forget.
|
||||
* @return a boolean value indicating whether the given session ID was even being remembered.
|
||||
* @see #remember(Object)
|
||||
*/
|
||||
boolean forget(Object sessionId) {
|
||||
return this.cachedSessionIds.remove(ObjectUtils.nullSafeHashCode(sessionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rememvers the given {@link Object session ID}.
|
||||
*
|
||||
* @param sessionId {@link Object} containing the session ID to remember.
|
||||
* @return a boolean value whether Spring Session is interested in and will remember
|
||||
* this given session ID.
|
||||
* @see #forget(Object)
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
boolean remember(Object sessionId) {
|
||||
return (isProxyRegion() && this.cachedSessionIds.add(ObjectUtils.nullSafeHashCode(sessionId)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Session toSession(Object obj) {
|
||||
return (obj instanceof Session ? (Session) obj : null);
|
||||
return isProxyRegion() && this.cachedSessionIds.add(ObjectUtils.nullSafeHashCode(sessionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts the given {@link Object} into a {@link Session} iff the {@link Object} is a {@link Session}.
|
||||
*
|
||||
* Otherwise, this method attempts to use the supplied {@link String session ID} to create a {@link Session}
|
||||
* containing only the ID.
|
||||
*
|
||||
* @param obj {@link Object} to evaluate as a {@link Session}.
|
||||
* @param sessionId {@link String} containing the session ID.
|
||||
* @return a {@link Session} from the given {@link Object}
|
||||
* or a {@link Session} containing only the supplied {@link String session ID}.
|
||||
* @throws IllegalStateException if the given {@link Object} is not a {@link Session}
|
||||
* and {@link String session ID} was not supplied.
|
||||
*/
|
||||
Session toSession(Object obj, String sessionId) {
|
||||
|
||||
return obj instanceof Session ? (Session) obj
|
||||
: Optional.ofNullable(sessionId)
|
||||
.filter(StringUtils::hasText)
|
||||
.map(SessionIdHolder::create)
|
||||
.orElseThrow(() -> newIllegalStateException(
|
||||
"Minimally, the session ID [%s] must be known to trigger a Session event", sessionId));
|
||||
}
|
||||
/**
|
||||
* Callback method triggered when an entry is created in the GemFire cache {@link Region}.
|
||||
*
|
||||
* @param event {@link EntryEvent} containing the details of the cache {@link Region} operation.
|
||||
* @param event {@link EntryEvent} containing the details of the cache operation.
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see #handleCreated(String, Session)
|
||||
*/
|
||||
@Override
|
||||
public void afterCreate(EntryEvent<Object, Session> event) {
|
||||
if (isCreate(event)) {
|
||||
handleCreated(event.getKey().toString(), toSession(event.getNewValue()));
|
||||
}
|
||||
|
||||
Optional.ofNullable(event)
|
||||
.filter(this::isCreate)
|
||||
.ifPresent(it -> {
|
||||
|
||||
String sessionId = it.getKey().toString();
|
||||
|
||||
handleCreated(sessionId, toSession(it.getNewValue(), sessionId));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method triggered when an entry is destroyed in the GemFire cache
|
||||
* {@link Region}.
|
||||
* Callback method triggered when an entry is destroyed in the GemFire cache {@link Region}.
|
||||
*
|
||||
* @param event an EntryEvent containing the details of the cache operation.
|
||||
* @param event {@link EntryEvent} containing the details of the cache operation.
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see #handleDestroyed(String, Session)
|
||||
*/
|
||||
@Override
|
||||
public void afterDestroy(EntryEvent<Object, Session> event) {
|
||||
handleDestroyed(event.getKey().toString(), toSession(event.getOldValue()));
|
||||
|
||||
Optional.ofNullable(event)
|
||||
.ifPresent(it -> {
|
||||
|
||||
String sessionId = event.getKey().toString();
|
||||
|
||||
handleDestroyed(sessionId, toSession(event.getOldValue(), sessionId));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method triggered when an entry is invalidated in the GemFire cache
|
||||
* {@link Region}.
|
||||
* Callback method triggered when an entry is invalidated in the GemFire cache {@link Region}.
|
||||
*
|
||||
* @param event an EntryEvent containing the details of the cache operation.
|
||||
* @param event {@link EntryEvent} containing the details of the cache operation.
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see #handleExpired(String, Session)
|
||||
*/
|
||||
@Override
|
||||
public void afterInvalidate(EntryEvent<Object, Session> event) {
|
||||
handleExpired(event.getKey().toString(), toSession(event.getOldValue()));
|
||||
|
||||
Optional.ofNullable(event)
|
||||
.ifPresent(it -> {
|
||||
|
||||
String sessionId = event.getKey().toString();
|
||||
|
||||
handleExpired(sessionId, toSession(event.getOldValue(), sessionId));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -402,12 +461,12 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @param session a reference to the Session triggering the event.
|
||||
* @see org.springframework.session.events.SessionCreatedEvent
|
||||
* @see org.springframework.session.Session
|
||||
* @see #newSessionCreatedEvent(Session, String)
|
||||
* @see #newSessionCreatedEvent(Session)
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
*/
|
||||
protected void handleCreated(String sessionId, Session session) {
|
||||
remember(sessionId);
|
||||
publishEvent(newSessionCreatedEvent(session, sessionId));
|
||||
publishEvent(newSessionCreatedEvent(session));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,13 +476,13 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @param session a reference to the Session triggering the event.
|
||||
* @see org.springframework.session.events.SessionDeletedEvent
|
||||
* @see org.springframework.session.Session
|
||||
* @see #newSessionDeletedEvent(Session, String)
|
||||
* @see #newSessionDeletedEvent(Session)
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
* @see #forget(Object)
|
||||
*/
|
||||
protected void handleDeleted(String sessionId, Session session) {
|
||||
forget(sessionId);
|
||||
publishEvent(newSessionDeletedEvent(session, sessionId));
|
||||
publishEvent(newSessionDeletedEvent(session));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,13 +492,13 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @param session a reference to the Session triggering the event.
|
||||
* @see org.springframework.session.events.SessionDestroyedEvent
|
||||
* @see org.springframework.session.Session
|
||||
* @see #newSessionDestroyedEvent(Session, String)
|
||||
* @see #newSessionDestroyedEvent(Session)
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
* @see #forget(Object)
|
||||
*/
|
||||
protected void handleDestroyed(String sessionId, Session session) {
|
||||
forget(sessionId);
|
||||
publishEvent(newSessionDestroyedEvent(session, sessionId));
|
||||
publishEvent(newSessionDestroyedEvent(session));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -449,41 +508,33 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @param session a reference to the Session triggering the event.
|
||||
* @see org.springframework.session.events.SessionExpiredEvent
|
||||
* @see org.springframework.session.Session
|
||||
* @see #newSessionExpiredEvent(Session, String)
|
||||
* @see #newSessionExpiredEvent(Session)
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
* @see #forget(Object)
|
||||
*/
|
||||
protected void handleExpired(String sessionId, Session session) {
|
||||
forget(sessionId);
|
||||
publishEvent(newSessionExpiredEvent(session, sessionId));
|
||||
publishEvent(newSessionExpiredEvent(session));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private SessionCreatedEvent newSessionCreatedEvent(Session session, String sessionId) {
|
||||
|
||||
return (session != null ? new SessionCreatedEvent(this, session)
|
||||
: new SessionCreatedEvent(this, sessionId));
|
||||
private SessionCreatedEvent newSessionCreatedEvent(Session session) {
|
||||
return new SessionCreatedEvent(this, session);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private SessionDeletedEvent newSessionDeletedEvent(Session session, String sessionId) {
|
||||
|
||||
return (session != null ? new SessionDeletedEvent(this, session)
|
||||
: new SessionDeletedEvent(this, sessionId));
|
||||
private SessionDeletedEvent newSessionDeletedEvent(Session session) {
|
||||
return new SessionDeletedEvent(this, session);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private SessionDestroyedEvent newSessionDestroyedEvent(Session session, String sessionId) {
|
||||
|
||||
return (session != null ? new SessionDestroyedEvent(this, session)
|
||||
: new SessionDestroyedEvent(this, sessionId));
|
||||
private SessionDestroyedEvent newSessionDestroyedEvent(Session session) {
|
||||
return new SessionDestroyedEvent(this, session);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private SessionExpiredEvent newSessionExpiredEvent(Session session, String sessionId) {
|
||||
|
||||
return (session != null ? new SessionExpiredEvent(this, session)
|
||||
: new SessionExpiredEvent(this, sessionId));
|
||||
private SessionExpiredEvent newSessionExpiredEvent(Session session) {
|
||||
return new SessionExpiredEvent(this, session);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -498,8 +549,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
try {
|
||||
getApplicationEventPublisher().publishEvent(event);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
getLogger().error(String.format("Error occurred publishing event [%s]", event), t);
|
||||
catch (Throwable cause) {
|
||||
getLogger().error(String.format("Error occurred while publishing event [%s]", event), cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,9 +189,10 @@ public class GemFireCacheTypeAwareRegionFactoryBean<K, V>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Interest<K>[] registerInterests(boolean register) {
|
||||
return (!register ? new Interest[0] : new Interest[] {
|
||||
new Interest<>("ALL_KEYS", InterestResultPolicy.KEYS)
|
||||
});
|
||||
|
||||
return register
|
||||
? new Interest[] { new Interest<>("ALL_KEYS", InterestResultPolicy.KEYS) }
|
||||
: new Interest[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,21 +18,26 @@ package org.springframework.session.data.gemfire.support;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.RegionShortcut;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
|
||||
/**
|
||||
* GemFireUtils is an abstract, extensible utility class for working with GemFire types
|
||||
* and functionality and is used by Spring Session's GemFire adapter support classes.
|
||||
* {@link GemFireUtils} is an abstract, extensible utility class for working with GemFire objects and types.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public abstract class GemFireUtils {
|
||||
@@ -62,14 +67,17 @@ public abstract class GemFireUtils {
|
||||
/**
|
||||
* Determines whether the GemFire cache is a client.
|
||||
*
|
||||
* @param gemFireCache a reference to the GemFire cache.
|
||||
* @param gemfireCache a reference to the GemFire cache.
|
||||
* @return a boolean value indicating whether the GemFire cache is a client.
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
public static boolean isClient(GemFireCache gemFireCache) {
|
||||
boolean client = (gemFireCache instanceof ClientCache);
|
||||
client &= (!(gemFireCache instanceof GemFireCacheImpl) || ((GemFireCacheImpl) gemFireCache).isClient());
|
||||
public static boolean isClient(GemFireCache gemfireCache) {
|
||||
|
||||
boolean client = (gemfireCache instanceof ClientCache);
|
||||
|
||||
client &= (!(gemfireCache instanceof GemFireCacheImpl) || ((GemFireCacheImpl) gemfireCache).isClient());
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -127,16 +135,28 @@ public abstract class GemFireUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link Region} is a PROXY, which would be indicated by the {@link Region}
|
||||
* having a {@link DataPolicy} of {@link DataPolicy#EMPTY}.
|
||||
* Determines whether the given {@link Region} is a {@literal PROXY}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link Region} is a PROXY.
|
||||
* @param region {@link Region} to evaluate as a {@literal PROXY}; must not be {@literal null}.
|
||||
* @return a boolean value indicating whether the {@link Region} is a {@literal PROXY}.
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
public static boolean isProxy(Region<?, ?> region) {
|
||||
return DataPolicy.EMPTY.equals(region.getAttributes().getDataPolicy());
|
||||
|
||||
RegionAttributes regionAttributes = region.getAttributes();
|
||||
|
||||
DataPolicy regionDataPolicy = regionAttributes.getDataPolicy();
|
||||
|
||||
boolean proxy = DataPolicy.EMPTY.equals(regionDataPolicy);
|
||||
|
||||
proxy |= proxy || Optional.ofNullable(regionDataPolicy)
|
||||
.filter(DataPolicy.PARTITION::equals)
|
||||
.map(it -> regionAttributes.getPartitionAttributes())
|
||||
.filter(partitionAttributes -> partitionAttributes.getLocalMaxMemory() <= 0)
|
||||
.isPresent();
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2017 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
|
||||
*
|
||||
* http://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 org.springframework.session.data.gemfire.support;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.EntryEvent;
|
||||
import org.apache.geode.cache.Operation;
|
||||
import org.apache.geode.cache.Region;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link SessionIdHolder} class is a Spring Session {@link Session} implementation that only holds
|
||||
* the {@link String ID} of the {@link Session}.
|
||||
*
|
||||
* This implementation is only used in case Apache Geode or Pivotal GemFire returns a {@literal null} (old) value
|
||||
* in a {@link Region} {@link EntryEvent} triggered by a {@link Operation#DESTROY} or {@link Operation#INVALIDATE}
|
||||
* operation.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see org.apache.geode.cache.Operation
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.session.data.gemfire.support.SessionIdHolder
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public final class SessionIdHolder extends AbstractSession {
|
||||
|
||||
private final String sessionId;
|
||||
|
||||
/***
|
||||
* Factory method to create an instance of the {@link SessionIdHolder} initialized with
|
||||
* the given {@link String session ID}.
|
||||
*
|
||||
* @param sessionId {@link String} containing the session ID used to initialize
|
||||
* the new instance of {@link SessionIdHolder}.
|
||||
* @return a new instance of {@link SessionIdHolder} initialized with
|
||||
* the given {@link String session ID}.
|
||||
* @throws IllegalArgumentException if session ID is {@literal null} or empty.
|
||||
* @see #SessionIdHolder(String)
|
||||
*/
|
||||
public static SessionIdHolder create(String sessionId) {
|
||||
return new SessionIdHolder(sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@link SessionIdHolder} initialized with
|
||||
* the given {@link String session ID}.
|
||||
*
|
||||
* @param sessionId {@link String} containing the session ID used to initialize
|
||||
* the new instance of {@link SessionIdHolder}.
|
||||
* @throws IllegalArgumentException if session ID is {@literal null} or empty.
|
||||
*/
|
||||
public SessionIdHolder(String sessionId) {
|
||||
|
||||
this.sessionId = Optional.ofNullable(sessionId)
|
||||
.filter(StringUtils::hasText)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Session ID [%s] is required", sessionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link String ID} of this {@link Session}.
|
||||
*
|
||||
* @return the {@link String ID} of this {@link Session}.
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Session)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Session that = (Session) obj;
|
||||
|
||||
return ObjectUtils.nullSafeEquals(this.getId(), that.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getId());
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getId();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,10 +18,11 @@ package org.springframework.session.data.gemfire.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.willThrow;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
@@ -31,6 +32,7 @@ import org.junit.Test;
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.PartitionAttributes;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.RegionShortcut;
|
||||
@@ -38,34 +40,44 @@ import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
|
||||
/**
|
||||
* The GemFireUtilsTest class is a test suite of test cases testing the contract and
|
||||
* functionality of the GemFireUtils utility class.
|
||||
* Unit tests for {@link GemFireUtils}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.session.data.gemfire.support.GemFireUtils
|
||||
*/
|
||||
public class GemFireUtilsTests {
|
||||
|
||||
@Test
|
||||
public void closeNonNullCloseableSuccessfullyReturnsTrue() throws IOException {
|
||||
public void closeNonNullCloseableReturnsTrue() throws IOException {
|
||||
|
||||
Closeable mockCloseable = mock(Closeable.class);
|
||||
|
||||
assertThat(GemFireUtils.close(mockCloseable)).isTrue();
|
||||
|
||||
verify(mockCloseable, times(1)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeNonNullCloseableObjectThrowingIOExceptionReturnsFalse() throws IOException {
|
||||
public void closeNonNullCloseableThrowingIOExceptionReturnsFalse() throws IOException {
|
||||
|
||||
Closeable mockCloseable = mock(Closeable.class);
|
||||
willThrow(new IOException("test")).given(mockCloseable).close();
|
||||
|
||||
doThrow(new IOException("test")).when(mockCloseable).close();
|
||||
|
||||
assertThat(GemFireUtils.close(mockCloseable)).isFalse();
|
||||
|
||||
verify(mockCloseable, times(1)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeNullCloseableObjectReturnsFalse() {
|
||||
public void closeNullCloseableReturnsFalse() {
|
||||
assertThat(GemFireUtils.close(null)).isFalse();
|
||||
}
|
||||
|
||||
@@ -101,6 +113,7 @@ public class GemFireUtilsTests {
|
||||
|
||||
@Test
|
||||
public void clientRegionShortcutIsLocal() {
|
||||
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL)).isTrue();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_HEAP_LRU)).isTrue();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_OVERFLOW)).isTrue();
|
||||
@@ -110,6 +123,7 @@ public class GemFireUtilsTests {
|
||||
|
||||
@Test
|
||||
public void clientRegionShortcutIsNotLocal() {
|
||||
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY)).isFalse();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_OVERFLOW)).isFalse();
|
||||
@@ -123,6 +137,7 @@ public class GemFireUtilsTests {
|
||||
|
||||
@Test
|
||||
public void clientRegionShortcutIsNotProxy() {
|
||||
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_OVERFLOW)).isFalse();
|
||||
@@ -134,19 +149,14 @@ public class GemFireUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionShortcutIsProxy() {
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY)).isTrue();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY_REDUNDANT)).isTrue();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PROXY)).isTrue();
|
||||
}
|
||||
public void emptyRegionIsProxy() {
|
||||
|
||||
@Test
|
||||
public void regionIsProxy() {
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
given(mockRegion.getAttributes()).willReturn(mockRegionAttributes);
|
||||
given(mockRegionAttributes.getDataPolicy()).willReturn(DataPolicy.EMPTY);
|
||||
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
|
||||
when(mockRegionAttributes.getDataPolicy()).thenReturn(DataPolicy.EMPTY);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isTrue();
|
||||
|
||||
@@ -155,8 +165,54 @@ public class GemFireUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionIsNotProxy() {
|
||||
public void partitionRegionWithNoLocalMaxMemoryIsProxy() {
|
||||
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
PartitionAttributes mockPartitionAttributes = mock(PartitionAttributes.class);
|
||||
|
||||
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
|
||||
when(mockRegionAttributes.getDataPolicy()).thenReturn(DataPolicy.PARTITION);
|
||||
when(mockRegionAttributes.getPartitionAttributes()).thenReturn(mockPartitionAttributes);
|
||||
when(mockPartitionAttributes.getLocalMaxMemory()).thenReturn(0);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPartitionAttributes();
|
||||
verify(mockPartitionAttributes, times(1)).getLocalMaxMemory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void partitionRegionWithNegativeLocalMaxMemoryIsProxy() {
|
||||
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
PartitionAttributes mockPartitionAttributes = mock(PartitionAttributes.class);
|
||||
|
||||
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
|
||||
when(mockRegionAttributes.getDataPolicy()).thenReturn(DataPolicy.PARTITION);
|
||||
when(mockRegionAttributes.getPartitionAttributes()).thenReturn(mockPartitionAttributes);
|
||||
when(mockPartitionAttributes.getLocalMaxMemory()).thenReturn(-1);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPartitionAttributes();
|
||||
verify(mockPartitionAttributes, times(1)).getLocalMaxMemory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void normalRegionIsNotProxy() {
|
||||
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
given(mockRegion.getAttributes()).willReturn(mockRegionAttributes);
|
||||
@@ -168,8 +224,89 @@ public class GemFireUtilsTests {
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void partitionRegionWithLocalMaxMemoryIsNotProxy() {
|
||||
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
PartitionAttributes mockPartitionAttributes = mock(PartitionAttributes.class);
|
||||
|
||||
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
|
||||
when(mockRegionAttributes.getDataPolicy()).thenReturn(DataPolicy.PARTITION);
|
||||
when(mockRegionAttributes.getPartitionAttributes()).thenReturn(mockPartitionAttributes);
|
||||
when(mockPartitionAttributes.getLocalMaxMemory()).thenReturn(1);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPartitionAttributes();
|
||||
verify(mockPartitionAttributes, times(1)).getLocalMaxMemory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void partitionRegionWithNoPartitionAttributesIsNotProxy() {
|
||||
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
|
||||
when(mockRegionAttributes.getDataPolicy()).thenReturn(DataPolicy.PARTITION);
|
||||
when(mockRegionAttributes.getPartitionAttributes()).thenReturn(null);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPartitionAttributes();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preloadedRegionIsNotProxy() {
|
||||
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
given(mockRegion.getAttributes()).willReturn(mockRegionAttributes);
|
||||
given(mockRegionAttributes.getDataPolicy()).willReturn(DataPolicy.PRELOADED);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replicateRegionIsNotProxy() {
|
||||
|
||||
Region mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
given(mockRegion.getAttributes()).willReturn(mockRegionAttributes);
|
||||
given(mockRegionAttributes.getDataPolicy()).willReturn(DataPolicy.REPLICATE);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionShortcutIsProxy() {
|
||||
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY)).isTrue();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY_REDUNDANT)).isTrue();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PROXY)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionShortcutIsNotProxy() {
|
||||
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_OVERFLOW)).isFalse();
|
||||
@@ -194,6 +331,7 @@ public class GemFireUtilsTests {
|
||||
|
||||
@Test
|
||||
public void toRegionPath() {
|
||||
|
||||
assertThat(GemFireUtils.toRegionPath("A")).isEqualTo("/A");
|
||||
assertThat(GemFireUtils.toRegionPath("Example")).isEqualTo("/Example");
|
||||
assertThat(GemFireUtils.toRegionPath("/Example")).isEqualTo("//Example");
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2017 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
|
||||
*
|
||||
* http://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 org.springframework.session.data.gemfire.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SessionIdHolder}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.session.Session
|
||||
* @see org.springframework.session.data.gemfire.support.SessionIdHolder
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class SessionIdHolderTests {
|
||||
|
||||
@Test
|
||||
public void createSessionIdHolderWithId() {
|
||||
|
||||
SessionIdHolder session = SessionIdHolder.create("12345");
|
||||
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.getId()).isEqualTo("12345");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createSessionIdHolderWithEmptyId() {
|
||||
|
||||
try {
|
||||
SessionIdHolder.create(" ");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Session ID [ ] is required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createSessionIdHolderWithNoId() {
|
||||
|
||||
try {
|
||||
SessionIdHolder.create(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Session ID [null] is required");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithSameSessionReturnsTrue() {
|
||||
|
||||
Session session = SessionIdHolder.create("12345");
|
||||
|
||||
assertThat(session.equals(session)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithEqualSessionsReturnsTrue() {
|
||||
|
||||
Session sessionOne = SessionIdHolder.create("12345");
|
||||
Session sessionTwo = SessionIdHolder.create("12345");
|
||||
|
||||
assertThat(sessionOne.equals(sessionTwo)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void equalsWithUnequalSessionsReturnsFalse() {
|
||||
|
||||
Session sessionOne = SessionIdHolder.create("123");
|
||||
Session sessionTwo = SessionIdHolder.create("12345");
|
||||
|
||||
assertThat(sessionOne.equals(sessionTwo)).isFalse();
|
||||
assertThat(sessionTwo.equals(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hashCodeForSameSessionIsEqual() {
|
||||
|
||||
Session session = SessionIdHolder.create("12345");
|
||||
|
||||
assertThat(session.hashCode()).isEqualTo(session.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hashCodeWithEqualSessionsIsEqual() {
|
||||
|
||||
Session sessionOne = SessionIdHolder.create("12345");
|
||||
Session sessionTwo = SessionIdHolder.create("12345");
|
||||
|
||||
assertThat(sessionOne.hashCode()).isEqualTo(sessionTwo.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hashCodeForUnequalSessionsAreNotEqual() {
|
||||
|
||||
Session sessionOne = SessionIdHolder.create("123");
|
||||
Session sessionTwo = SessionIdHolder.create("12345");
|
||||
|
||||
assertThat(sessionOne.hashCode()).isNotEqualTo(sessionTwo.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringReturnsSessionId() {
|
||||
assertThat(SessionIdHolder.create("12345").toString()).isEqualTo("12345");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user